> ## Documentation Index
> Fetch the complete documentation index at: https://platform.eldros.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# HTTP / REST / A2A agents

> Traces, simulation, and production options for any HTTP-based agent.

## 1. Add traces

Install the SDK and call `init()` once at startup. Wrap each user↔agent exchange in a `turn()`:

```python theme={null}
import eldros_sdk

eldros_sdk.init(traffic_type="prod")

@app.post("/chat")
async def chat(request: Request):
    body = await request.json()
    user_msg = body["message"]

    with eldros_sdk.turn(user_msg, session_id=body.get("session_id")) as t:
        reply = await agent.respond(user_msg)   # LLM call nests under the turn automatically
        t.reply(reply)                          # records the assistant turn

    return {"reply": reply}
```

`turn()` opens a span and makes it the active span — any [auto-instrumented LLM or tool call](/docs/tracing)
inside nests underneath it automatically. `t.reply()` records the assistant response as the transcript.

## 2. Connect simulation

When Eldros runs a test scenario it sends W3C `traceparent` + `baggage` headers on every request.
Continue them with one line around your handler:

```python theme={null}
@app.post("/chat")
async def chat(request: Request):
    body = await request.json()
    user_msg = body["message"]

    with eldros_sdk.trace_context(dict(request.headers)):   # ← add this
        with eldros_sdk.turn(user_msg, session_id=body.get("session_id")) as t:
            reply = await agent.respond(user_msg)
            t.reply(reply)

    return {"reply": reply}
```

`trace_context` works with FastAPI, Flask, Starlette, A2A, JSON-RPC — any HTTP framework.
On production requests (no Eldros headers) it is a no-op, so you keep one handler for both.

When the headers are present, every span is stamped with:

* **`episode.id`** — links the trace to the specific test run
* **`traffic_type="simulation"`** — keeps test traffic out of your production views

<Note>
  For simulation, `t.reply()` is optional — Eldros already has the transcript from the
  platform side. `turn()` is still required so each LLM/tool span is linked to the correct
  turn, giving you a structured trace even without the client-side transcript.
</Note>

## 3. Integration modes

Pick the mode that matches what you need:

**Simulation + production observability (recommended)**\
Full transcript and traces for both production and eval runs:

```python theme={null}
eldros_sdk.init(traffic_type="prod")
# handler: trace_context + turn() + t.reply()
```

**Simulation only**\
Only export during Eldros-driven test runs. Production traffic goes through normally
but nothing is sent to the backend. `t.reply()` optional — platform has the transcript:

```python theme={null}
eldros_sdk.init(traffic_type="prod", simulation_only=True)
# handler: trace_context + turn() — t.reply() optional
```

**Production observability only**\
No simulation integration. Full transcript required since there is no platform-side record:

```python theme={null}
eldros_sdk.init(traffic_type="prod")
# handler: turn() + t.reply() — no trace_context needed
```

<Note>
  Traces without `turn()` — in any mode — cannot be correlated to specific conversation
  turns. The transcript is what gets judged; traces explain the verdict.
</Note>

## A2A agents

A2A is JSON-RPC over HTTP — the same pattern applies. Use the official `a2a-sdk` and
place `trace_context` inside your `AgentExecutor.execute()`:

```python theme={null}
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue

class MyAgentExecutor(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
        user_msg = context.get_user_input()

        with eldros_sdk.trace_context(context.request.headers):   # A2A request headers
            with eldros_sdk.turn(user_msg) as t:
                reply = await agent.respond(user_msg)
                t.reply(reply)

        # enqueue A2A response events as normal
```

Everything else — `init()`, `simulation_only`, the three integration modes — is identical
to the HTTP section above.
