---
title: "Trigger agent generation"
method: POST
path: "/v1/projects/{project_id}/sessions/{session_id}/generate"
tags: ["Sessions"]
---

# Trigger agent generation

`POST /v1/projects/{project_id}/sessions/{session_id}/generate`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/sessions/{session_id}/generate`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Triggers the agent to generate a response based on the current conversation. Background by default: returns `202 Accepted` immediately while the generation runs. Pass ?wait=true to block and receive the assistant reply (or a requires_action status if the agent needs client tool outputs) in the response.

## Path parameters

- `session_id` string, required

## Query parameters

- `wait` boolean

## Request body

- GenerateSessionRequest
  - `model` string: Optional model override
  - `tool_context` object, nullable: Key-value pairs forwarded as `X-Naturali-Context-<key>` headers on every `http` and `mcp` tool call in this generation. The header name is the deployment's configured context prefix (`X-Naturali-Context-` by default) plus the key verbatim — no character is re-cased. Keys are never case-converted — they round-trip exactly as sent. An invalid or colliding key is rejected with `400 INVALID_TOOL_CONTEXT_KEY`.

## Response `200`

Agent reply or requires_action (only when `?wait=true`)

- union
  - GenerateConversationMessageCompleted
    - `status` 'completed', required: Indicates generation finished successfully.
    - `content` string, required: The AI-generated text of the reply. This is the canonical field for the assistant's response text.
    - `message` ConversationMessageRecord, required
      - `document_id` string: Document ID
      - `role` 'user' | 'assistant' | 'system': Role of the message sender
      - `actor_id` string, nullable: Optional actor ID associated with this message
      - `agent_id` string, nullable: Optional agent ID that generated this message (set for assistant messages produced by generate)
      - `position` integer: Zero-based position in the conversation
      - `metadata` MetadataBag: Caller-owned annotations on a resource, stored as the object they were written as: the types a value was written with are the types a read returns, so a filter can ask an ordering question about a number. Unlike other body fields, keys are stored and returned verbatim in the casing supplied — they are not converted between snake_case and camelCase. No key is reserved, and that is the point: every piece of state the platform owns lives in its own typed column, so nothing written here reaches platform state. The platform never reads the bag — it is not an IAM context, not a policy input and not part of a prompt — which is what separates it from a tag bag.
      - `content` string, nullable: Full text content of the message
      - `idempotency_key` string, nullable: The idempotency key the message was posted with, null when none was sent. A channel that posts each inbound message under its provider's message id finds the transcript row for that message by this key.
    - `generation_id` string, required: ID of the underlying generation record.
    - `trace_id` string, required: Trace ID for observability.
    - `model` string: Model used for generation.
  - GenerateConversationMessageRequiresAction
    - `status` 'requires_action', required: Indicates the agent requires tool-call outputs before it can produce a reply. No message is persisted yet.
    - `generation_id` string, required: ID of the paused generation. Pass to the tool-outputs endpoint.
    - `trace_id` string, required: Trace ID for observability.
    - `required_action` object, required: Tool-call information the client must resolve.
      - `type` 'submit_tool_outputs'
      - `tool_calls` object[]
        - `id` string
        - `tool_name` string
        - `args` object

## Other responses

- `202`: Generation accepted and running in the background (default, when `wait` is omitted or `false`)
- `401`: Missing or invalid credentials.
- `403`: The credential is scoped to a different project, or the caller's role in the project does not carry this action.
- `404`: The resource does not exist (existence is not leaked).
- `409`: Generation already in progress
- `410`: Session has expired due to inactivity
- `429`: `QUOTA_EXCEEDED`: an `enforce`-mode generation quota is exhausted. `error.meta` carries `quota_id`, `metric`, `limit`, `window` and `resets_at`, with a `Retry-After` header. Only with `?wait=true`: a background call is answered `202` before the quota is read.
- `502`: Upstream AI provider error (AI_PROVIDER_ERROR). The error `meta` includes the `generation_id` and `trace_id` of the failed generation for post-mortem debugging via GET /v1/projects/{project_id}/generations/{generation_id}.

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
