> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.lakera.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.lakera.ai/_mcp/server.

# Connect your Agent

A **Stateful** Agent target normally expects Red's canonical contract: a
`{ message, sessionId }` request and a `{ message, sessionId }` response (see
[Supported contracts](/docs/red/connect-to-your-agent#supported-contracts)). If your
endpoint uses different field names, nests the reply deeper in the JSON, streams over
SSE, or returns the session id somewhere else, you can map those differences directly in
the target form — without deploying a wrapper.

The mapping lives in the **Connect your target's API** section, shown when you select
**Agent** and **Stateful**. Every field is optional: anything you leave blank keeps the
canonical behavior, so an empty section is exactly the standard Stateful contract.

If your API is highly custom — multi-step auth, non-HTTP transports, multi-request flows
— see [Creating a wrapper](/docs/red/creating-a-wrapper) instead and leave this section
at its defaults.

## Request

**Request body template** defines the JSON body Red sends on every turn. Put
`{{prompt}}` where the attack text goes; the rest of the template is sent verbatim.

```json
{
  "query": "{{prompt}}",
  "channel": "web"
}
```

The session id is never templated — configure it in the **Session** step below and Red
writes it into the body or header structurally. If you set a template, it defines the
entire request body; **Additional Fields** do not apply.

## Response

**Response format** selects how Red reads the assistant's reply — either a single JSON
body or a streamed SSE response.

Paths use a `$.` root, shown as a prefix in the form; enter the location after it, using
dot and bracket notation.

### JSON

For a single JSON response, set **Reply path** to the location of the reply text, for
example `$.data.answer` or `$.choices[0].message.content`. Blank keeps the canonical
`message` field.

```json
{
  "data": { "answer": "the model's reply" }
}
```

### SSE

For a target that streams its reply over server-sent events, select **SSE** and set:

1. **Delta path** — the location, in each event's JSON, of the text chunk to accumulate,
   for example `$.choices[0].delta.content`.
2. **Stop condition** — how Red knows the reply is complete: either a **sentinel** raw
   data line (for example `[DONE]`), or a **field** that equals a value (for example
   `$.response_state` equals `completed`).

Optionally, set an **include-when** condition to accumulate a chunk only when a field
matches — for example include an event only when `$.part_type` equals `answer`, so
reasoning or tool-call events are skipped.

## Session

Multi-turn targets keep a conversation going with a session id: Red **extracts** it from
the target's response and **sends it back** on every follow-up request. **Session**
tells Red where that id lives in each direction — whether it travels in the **body** (at
a path) or a **header** (by name). Red reads it out of the first response and writes it
into each subsequent request at that location. Blank keeps the canonical top-level
`sessionId` field.

During **Test Connection**, Red sends two messages and verifies that the second response
returns the same session id, confirming the mapping works end to end.