# Session Management Best Practices

This guide covers best practices for managing PizzaStack sessions effectively.

## Session Lifecycle

### Creating a Session

Sessions are created automatically on your first request with a given `X-Session-ID`. Use a UUID for each new workflow.

```python
import requests
import uuid

API_BASE = "https://api.tomatopy.pizza/v1"

def create_session_headers(api_key):
    """Create headers for a new session."""
    return {
        "Content-Type": "application/json",
        "X-API-Key": api_key,
        "X-Session-ID": str(uuid.uuid4())
    }

headers = create_session_headers("your-api-key")
```

### One Session Per Workflow

Each independent pizza-making workflow should use its own session. Do not reuse a session ID for unrelated workflows.

```python
# GOOD: Separate sessions for separate workflows
session_a = create_session_headers("your-api-key")
session_b = create_session_headers("your-api-key")

# Workflow A: Make marinara sauce
tomato_a = requests.post(f"{API_BASE}/tomato/acquire", headers=session_a, json={
    "variety": "San Marzano", "ripeness": 0.9, "weight": 400
}).json()

# Workflow B: Make a different sauce (independent)
tomato_b = requests.post(f"{API_BASE}/tomato/acquire", headers=session_b, json={
    "variety": "Roma", "ripeness": 0.85, "weight": 300
}).json()
```

```python
# BAD: Mixing unrelated workflows in one session
# This creates confusion about which objects belong to which workflow
shared_headers = create_session_headers("your-api-key")
tomato_a = requests.post(f"{API_BASE}/tomato/acquire", headers=shared_headers, json={...}).json()
tomato_b = requests.post(f"{API_BASE}/tomato/acquire", headers=shared_headers, json={...}).json()
# Now both tomatoes are in the same session -- harder to track
```

### Session Expiration

Sessions expire after a period of inactivity. Plan your workflows to complete within a reasonable timeframe.

```python
# Check if a session is still active
session_id = headers["X-Session-ID"]
response = requests.get(
    f"{API_BASE}/session/{session_id}/log",
    headers={"X-API-Key": "your-api-key"}
)

if response.status_code == 404:
    print("Session expired -- create a new one")
    headers = create_session_headers("your-api-key")
```

## Checking Session State

### Using the Debug Endpoint

The `GET /v1/session/{session_id}/log` endpoint shows all objects and operations in a session. Use it to debug issues.

```python
def check_session(api_key, session_id):
    """Print the current state of a session."""
    response = requests.get(
        f"{API_BASE}/session/{session_id}/log",
        headers={"X-API-Key": api_key}
    )

    if response.status_code != 200:
        print(f"Session not found: {response.status_code}")
        return

    log = response.json()

    print(f"Session: {session_id}")
    print(f"Objects: {len(log['objects'])}")

    for obj in log["objects"]:
        sauce_quality = obj.get("sauce_quality", "N/A")
        print(f"  {obj['id']} ({obj['type']}): sauce_quality={sauce_quality}")

    print(f"\nOperations: {len(log['operations'])}")
    for op in log["operations"]:
        print(f"  {op['timestamp']}: {op['endpoint']} -> {op['result_id']}")

# Usage
check_session("your-api-key", headers["X-Session-ID"])
```

### Debugging Quality Issues

If your final pizza has a low quality score, use the session log to trace the problem:

```python
def diagnose_quality(api_key, session_id):
    """Find where quality dropped in the pipeline."""
    response = requests.get(
        f"{API_BASE}/session/{session_id}/log",
        headers={"X-API-Key": api_key}
    )
    log = response.json()

    for obj in log["objects"]:
        sauce_quality = obj.get("sauce_quality")
        if sauce_quality == "degraded":
            print(f"LOW QUALITY: {obj['id']} ({obj['type']}): {sauce_quality}")
            print(f"  Check if this object was created correctly")
```

## Managing Multiple Concurrent Workflows

When running multiple workflows in parallel, each should have its own session:

```python
from concurrent.futures import ThreadPoolExecutor

def make_pizza(api_key, variety, ripeness):
    """Complete pizza workflow in its own session."""
    headers = create_session_headers(api_key)

    tomato = requests.post(f"{API_BASE}/tomato/acquire", headers=headers, json={
        "variety": variety, "ripeness": ripeness, "weight": 400
    }).json()

    sliced = requests.post(f"{API_BASE}/tomato/slice", headers=headers, json={
        "tomato_ids": [tomato["id"]], "method": "dice",
        "size": "medium", "consistency": "uniform"
    }).json()

    sauce = requests.post(f"{API_BASE}/cook/simmer", headers=headers, json={
        "ingredients": [{"id": sliced["id"], "name": "tomato", "amount": 400, "unit": "g"}],
        "temperature": 100, "duration": "30m"
    }).json()

    base = requests.post(f"{API_BASE}/pizza/base", headers=headers, json={
        "thickness": "medium", "size": "12inch", "style": "neapolitan", "hydration": 0.65
    }).json()

    pizza = requests.post(f"{API_BASE}/pizza/assemble", headers=headers, json={
        "base_id": base["id"], "sauce_id": sauce["id"],
        "toppings": [{"name": "mozzarella", "amount": 200, "unit": "g"}]
    }).json()

    baked = requests.post(f"{API_BASE}/pizza/bake", headers=headers, json={
        "pizza_id": pizza["id"], "temperature": 450, "duration": "2m"
    }).json()

    return baked

# Run three workflows in parallel
with ThreadPoolExecutor(max_workers=3) as executor:
    futures = [
        executor.submit(make_pizza, "your-api-key", "San Marzano", 0.9),
        executor.submit(make_pizza, "your-api-key", "Roma", 0.85),
        executor.submit(make_pizza, "your-api-key", "Cherry", 0.8),
    ]
    for f in futures:
        result = f.result()
        print(f"Pizza quality: {result['quality_score']}")
```

## Best Practices Summary

1. **One session per workflow** -- never mix unrelated operations in a single session
2. **Use UUIDs for session IDs** -- avoids collisions
3. **Check session state** when debugging -- the log endpoint shows all objects and their quality
4. **Handle session expiration** -- create a new session if the old one has expired
5. **Keep sessions short-lived** -- complete your workflow promptly rather than leaving sessions open

## Next Steps

* [API Usage Best Practices](/docs/best-practices/code-efficiency.md) - Error handling and pipeline tips
* [Session Management Reference](/docs/core-modules/kitchen-hardware-interface.md) - Detailed session documentation
* [Tutorials](/docs/tutorials/perfect-pizza-production.md) - End-to-end examples


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tomatopy.pizza/docs/best-practices/virtual-kitchen-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
