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

# Run with API

> Invoke an agent with the public API using your workspace API key, an agent ID, and a message

Use the public agent invoke endpoint when you want to send a message to an agent from your own app or service. In Fetch Hive, you can copy the request shape from **More** -> **Get Code** in the agents sidebar or from **Get Code** in the agent editor control bar.

## Authentication

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

See [API Keys](../workspace/api-keys) for how to create and manage keys.

## Endpoint

`POST https://api.fetchhive.com/v1/agent/invoke`

If you want Fetch Hive to generate the cURL example for you, open **Agents**, then use **More** -> **Get Code**. If you are already in the editor for a specific agent, click **Get Code** in the editor control bar instead.

## Request

Use this request shape:

| Field         | Type    | Required | Description                                                                                                                                                                                                                       |
| ------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agent`       | string  | Yes      | The agent ID                                                                                                                                                                                                                      |
| `message`     | string  | Yes      | The message you want to send to the agent                                                                                                                                                                                         |
| `streaming`   | boolean | No       | Whether the response should stream back as events                                                                                                                                                                                 |
| `thread_id`   | string  | No       | An arbitrary string identifying the conversation thread. Fetch Hive creates a new thread on first use and resumes it on subsequent calls with the same value.                                                                     |
| `messages`    | array   | No       | Previous conversation turns supplied by the caller. Used as context without persisting to the database. Each item: `{ "content": string, "role": "user" \| "assistant" \| "system", "attachments"?: array }`.                     |
| `attachments` | array   | No       | HTTPS file URLs attached to the current `message`. Each item can be a URL string or an object with `file_url`. Supported document files are CSV, XLSX, PDF, DOCX, and text/Markdown by extension. Images can also be passed here. |
| `metadata`    | object  | No       | Flat caller-defined metadata for audit and log filtering. This is not added to the agent prompt.                                                                                                                                  |

`metadata` must be flat and scalar-only: strings, numbers, booleans, or `null`. Nested objects and arrays return a validation error before the run starts.

`attachments` items can be simple URL strings:

```json theme={null}
[
  "https://example.com/customer-brief.pdf",
  "https://example.com/customer-brief.pdf"
]
```

They can also use this object shape when you want to provide metadata:

```json theme={null}
{
  "file_url": "https://example.com/customer-brief.pdf",
  "file_name": "customer-brief.pdf",
  "file_type": "application/pdf"
}
```

Only `https://` URLs are accepted. Up to five attachments are allowed per
message. Document attachments are
exposed to the agent through the system `read_file` tool as an
`<available_files>` manifest; the agent calls `read_file` before relying on
document contents. If an attachment URL or type is invalid, Fetch Hive returns
a `422` validation error instead of opening the stream. The error uses the
standard `error_code`, `error`, and `message` fields; `error` and `message` are
localized from the authenticated account language when available.

Supported document attachments:

* CSV: `text/csv`, `.csv`
* XLSX: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`, `.xlsx`
* PDF: `application/pdf`, `.pdf`
* DOCX: `application/vnd.openxmlformats-officedocument.wordprocessingml.document`, `.docx`
* Text and Markdown by extension: `.txt`, `.md`, `.markdown`

For extensionless URLs, such as Fetch Hive Media Library URLs, pass the URL
directly. Fetch Hive allow-lists the URL for `read_file`, and the file tool
detects the actual type when it fetches the file.

The in-app snippet shows the same body shape:

```json theme={null}
{
  "agent": "AGENT_UUID",
  "message": "Your message here",
  "streaming": true,
  "metadata": {
    "customer_id": "cus_123",
    "plan": "enterprise"
  }
}
```

## Basic example

```bash theme={null}
curl 'https://api.fetchhive.com/v1/agent/invoke' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  --data-raw '{
    "agent": "AGENT_UUID",
    "message": "Summarize the latest AI infrastructure trends",
    "metadata": {
      "customer_id": "cus_123",
      "plan": "enterprise"
    },
    "attachments": [
      "https://example.com/customer-brief.pdf"
    ],
    "streaming": true
  }' \
  --compressed
```

This matches the cURL snippet shown in the product. The invoke dialog currently shows **cURL**, while **Python** and **TypeScript** still show **Coming Soon**.

Use `metadata` for audit fields you want to see or filter in logs, such as customer IDs, plan names, regions, or experiment names. It is stored with the run and displayed under **User metadata** in logs. See [Invoke metadata](../user-tracking/invoke-metadata) for examples and log filtering details.

## Response

If `streaming` is `true`, the route returns a stream of events rather than one final JSON object. If the provider fails after the stream has opened, the route sends a final `error` event before closing the stream. If the client disconnects first, Fetch Hive treats it as a silent cancellation and does not create a failed agent run, bill usage, or report a provider-error event unless the provider had already completed and usage was committed.

### Streaming response

The stream can include a summary event, reasoning chunks, response chunks, tool events, a final usage event, or an error event. Events arrive in this order when all successful events are present: `summary` → `reasoning` → `response` → `tool` → `usage`. An `error` event can arrive instead of `usage` if the provider fails mid-stream.

Summary event (only emitted on threads with auto-summarization enabled):

```json theme={null}
{
  "type": "summary",
  "summary_text": "The conversation covered AI infrastructure trends. The user asked about evals and tool routing...",
  "original_token_count": 15234,
  "context_limit": 200000,
  "model": "gpt-4.1",
  "provider": "openai"
}
```

This event fires at the start of the stream when the accumulated thread history has crossed the auto-summarization threshold. It means the prior conversation was compressed into a summary before being sent to the model — the agent retains the context, but the raw history has been condensed. `original_token_count` is the token count before compression; `context_limit` is the model's total context window. You can surface this to users as a "conversation summarized" indicator, or ignore it — your app's behaviour is unaffected either way.

Reasoning event:

```json theme={null}
{
  "request_id": "req_019d52846ea37682b03522fd0695cc43",
  "type": "reasoning",
  "response": "Looking at the latest model releases..."
}
```

Response event:

```json theme={null}
{
  "request_id": "req_019d52846ea37682b03522fd0695cc43",
  "type": "response",
  "response": "Teams are standardizing around evals, routing, and observability.",
  "done": false
}
```

Tool event:

```json theme={null}
{
  "request_id": "req_019d52846ea37682b03522fd0695cc43",
  "type": "tool",
  "tool_id": "tool_123",
  "tool": "google_search",
  "tool_input": {
    "query": "latest AI infrastructure trends 2026"
  },
  "observation": {
    "results": []
  }
}
```

Final usage event:

```json theme={null}
{
  "request_id": "req_019d52846ea37682b03522fd0695cc43",
  "type": "usage",
  "usage": {
    "duration": 4.79230260848999,
    "input_tokens": {
      "total_tokens": 24,
      "cached_tokens": 0,
      "cached_read_tokens": 0,
      "cache_write_tokens": 0
    },
    "output_tokens": {
      "total_tokens": 170,
      "reasoning_tokens": 64
    },
    "total_tokens": 194
  },
  "stop_reason": "completed"
}
```

Error event:

```json theme={null}
{
  "request_id": "req_019d52846ea37682b03522fd0695cc43",
  "type": "error",
  "id": "msg_019d52846ea37682b03522fd0695cc43",
  "error": "openai provider stream error: HTTP 400: invalid request",
  "message": "openai provider stream error: HTTP 400: invalid request",
  "provider": "openai",
  "error_type": "provider_stream_error",
  "status_code": 502
}
```

### Non-streaming response

If `streaming` is `false`, the route returns one JSON response with the generated output, usage data, and the request ID you can use to inspect the run in **Logs**. Provider execution failures return `502 Bad Gateway` with an `error` message.

The exact output field can vary by provider, but the response includes the run metadata you need. For example:

```json theme={null}
{
  "request_id": "req_019d528660dd7e22b15e5b13a1931c50",
  "model": "gpt-5-nano-2025-08-07",
  "duration": 4.641960144042969,
  "response": "Teams are moving from simple wrappers to systems with evals, tool routing, and tighter cost controls.",
  "reasoning": "The request asks for a short summary of current infrastructure trends.",
  "usage": {
    "input_tokens": {
      "total_tokens": 24,
      "cached_tokens": 0,
      "cached_read_tokens": 0,
      "cache_write_tokens": 0
    },
    "output_tokens": {
      "total_tokens": 187,
      "reasoning_tokens": 64
    },
    "total_tokens": 211
  },
  "stop_reason": "completed"
}
```

If the agent uses tools, the non-streaming response can also include tool execution details.

## Multi-turn conversations

The invoke endpoint supports two approaches for multi-turn conversations.

### Persistent threads (Fetch Hive manages history)

Pass a `thread_id` — any string you choose — and Fetch Hive will automatically create the thread on the first call and resume it on every subsequent call with the same value. Message history is stored in Fetch Hive and included in the context automatically.

```bash theme={null}
# First turn
curl 'https://api.fetchhive.com/v1/agent/invoke' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "agent": "AGENT_UUID",
    "message": "What are the main AI infrastructure trends right now?",
    "streaming": true,
    "thread_id": "user-456-support-session"
  }'

# Second turn — same thread_id resumes the conversation
curl 'https://api.fetchhive.com/v1/agent/invoke' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "agent": "AGENT_UUID",
    "message": "Which of those trends have the most enterprise adoption?",
    "streaming": true,
    "thread_id": "user-456-support-session"
  }'
```

You can use any string as a `thread_id` — a user ID, session ID, ticket number, or any other identifier that makes sense for your use case.

### Stateless history (caller manages history)

If you prefer to manage conversation state yourself, pass the previous turns in the `messages` array. Fetch Hive uses the provided history for context but does not persist it.

```bash theme={null}
curl 'https://api.fetchhive.com/v1/agent/invoke' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "agent": "AGENT_UUID",
    "message": "Which of those trends have the most enterprise adoption?",
    "streaming": true,
    "messages": [
      {
        "content": "What are the main AI infrastructure trends right now?",
        "role": "user",
        "attachments": [
          {
            "file_url": "https://example.com/market-data.csv",
            "file_name": "market-data.csv",
            "file_type": "text/csv"
          }
        ]
      },
      { "content": "Teams are focusing on evals, tool routing, and observability.", "role": "assistant" }
    ]
  }'
```

For caller-managed sessions, send up to 50 account/workspace-owned Asset UUIDs
in `known_artifact_refs`. Put the UUIDs selected for the current turn in
`artifact_refs`; `attachments` plus `artifact_refs` can contain at most five
items. An `artifact_ref` must also appear in `known_artifact_refs`.

Persistent `thread_id` calls derive known artifacts from the saved chat and
ignore conflicting client discovery metadata. External document and image URLs
continue to use `attachments` or `messages[].attachments`. External audio URLs
are unsupported.

Streaming calls can receive an `artifact` event in addition to existing tool
events. Non-stream responses include an `artifacts` array.

Use `messages` when you already maintain your own chat state and do not need Fetch Hive to store the conversation history.

## Next steps

* [Logs](./logs)
* [Testing with Chat](./testing-with-chat)
* [Run with Python SDK](./run-with-python-sdk)
* [Run with Node.js SDK](./run-with-nodejs-sdk)
* [Run with Ruby SDK](./run-with-ruby-sdk)
* [Run with PHP SDK](./run-with-php-sdk)
