---
title: "Submit tool outputs"
method: POST
path: "/v1/projects/{project_id}/sessions/{session_id}/tool-outputs"
tags: ["Sessions"]
---

# Submit tool outputs

`POST /v1/projects/{project_id}/sessions/{session_id}/tool-outputs`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/sessions/{session_id}/tool-outputs`
- 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`)

Submits client tool outputs for a generation that returned requires_action. The agent continues its loop and returns the final or next requires_action result. A generation that did not run in the session's conversation is 404 (GENERATION_NOT_FOUND) and receives no outputs.

## Path parameters

- `session_id` string, required

## Request body

- SubmitSessionToolOutputsRequest
  - `generation_id` string, required: The generation ID from the requires_action response
  - `tool_outputs` object[], required
    - `tool_call_id` string, required
    - `output` unknown, required

## Response `200`

Generation result

- 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

- `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`: The generation is not paused on client tool calls (GENERATION_NOT_AWAITING_TOOL_OUTPUTS): it never paused, or its outputs were already submitted. Each pause accepts outputs once.

---

[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)
