> ## 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 Python SDK

> Invoke an agent from Python with the fetch-hive-sdk package

Use the official `fetch-hive-sdk` package when you want to send a message to an agent from Python. The SDK wraps the public [`POST /v1/agent/invoke`](../api-reference/agents/invoke) endpoint, handles authentication, supports streaming and multimodal inputs, and exposes both synchronous and `asyncio` variants.

## Installation

```bash theme={null}
pip install fetch-hive-sdk
```

The SDK requires Python 3.9+ and uses `httpx` under the hood.

## Authentication

Set the `FETCH_HIVE_API_KEY` environment variable to your workspace API key (the SDK reads it automatically):

```bash theme={null}
export FETCH_HIVE_API_KEY=fhk_...
```

```python theme={null}
from fetch_hive_sdk import FetchHive

client = FetchHive()
```

Or pass the key explicitly:

```python theme={null}
client = FetchHive(api_key="fhk_...")
```

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

## Basic example

Send a message to an agent and read the final response:

```python theme={null}
from fetch_hive_sdk import FetchHive

client = FetchHive()

reply = client.invoke_agent(
    agent="AGENT_UUID",
    message="Summarize the latest AI infrastructure trends",
)

print(reply["response"])
```

See the [non-streaming response shape](../api-reference/agents/invoke#response).

## Method reference

| Argument    | Type                                             | Required | Description                                                                                                                                      |
| ----------- | ------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `agent`     | `str`                                            | Yes      | The agent ID                                                                                                                                     |
| `message`   | `str`                                            | Yes      | The message you want to send                                                                                                                     |
| `thread_id` | `str`                                            | No       | An arbitrary string identifying a persistent conversation thread. Fetch Hive creates the thread on first use and resumes it on subsequent calls. |
| `messages`  | `list[dict]`                                     | No       | Caller-managed conversation history. Each item: `{"role": "user" \| "assistant" \| "system", "content": str}`.                                   |
| `user`      | `str`                                            | No       | Opaque caller identifier surfaced in [User Tracking](../user-tracking/overview)                                                                  |
| `metadata`  | `dict[str, str \| int \| float \| bool \| None]` | No       | Flat caller-defined metadata for audit and log filtering. See [Invoke metadata](../user-tracking/invoke-metadata)                                |

The SDK injects `streaming: false` for `invoke_agent`. To stream, use `invoke_agent_stream` (below).

## Handling the response

```python theme={null}
reply = client.invoke_agent(agent="AGENT_UUID", message="Hello")

print(reply["response"])      # final text
print(reply["model"])         # model identifier
print(reply["usage"])         # token usage breakdown
print(reply["request_id"])    # use this to look up the run in Logs
print(reply.get("tool_calls"))  # tool invocations made during the run
```

## Streaming

Use `invoke_agent_stream` to receive Server-Sent Events as they arrive. The method returns a generator that yields parsed event dicts:

```python theme={null}
for chunk in client.invoke_agent_stream(
    agent="AGENT_UUID",
    message="Summarize the latest AI infrastructure trends",
    thread_id="user-456-support-session",
):
    if chunk.get("type") == "response":
        print(chunk.get("response", ""), end="", flush=True)
    elif chunk.get("type") == "tool":
        print(f"\n[Calling tool: {chunk.get('tool')}]")
    elif chunk.get("type") == "usage":
        print("\n\nUsage:", chunk["usage"])
```

The stream yields the same event types documented in [Invoke Agent → Response](../api-reference/agents/invoke#response): `summary` (when auto-summarization fires), `reasoning`, `response`, `tool`, a final `usage` event, or an `error` event if the provider fails mid-stream.

### Async streaming

For `asyncio` applications, use `ainvoke_agent_stream`. It has the same arguments but returns an async iterator:

```python theme={null}
import asyncio
from fetch_hive_sdk import FetchHive

async def main():
    client = FetchHive()
    async for chunk in client.ainvoke_agent_stream(
        agent="AGENT_UUID",
        message="Hello",
        thread_id="user-456-support-session",
    ):
        if chunk.get("type") == "response":
            print(chunk.get("response", ""), end="", flush=True)

asyncio.run(main())
```

## Multi-turn conversations

### Persistent threads

Pass any string as `thread_id` and Fetch Hive will create the thread on the first call and resume it on subsequent calls with the same value:

```python theme={null}
client.invoke_agent(
    agent="AGENT_UUID",
    message="What are the main AI infrastructure trends right now?",
    thread_id="user-456-support-session",
)

client.invoke_agent(
    agent="AGENT_UUID",
    message="Which of those trends have the most enterprise adoption?",
    thread_id="user-456-support-session",
)
```

### Stateless history

Manage state yourself by passing the previous turns in `messages`. Fetch Hive uses the supplied history for context but does not persist it:

```python theme={null}
client.invoke_agent(
    agent="AGENT_UUID",
    message="Which of those trends have the most enterprise adoption?",
    messages=[
        {"role": "user", "content": "What are the main AI infrastructure trends right now?"},
        {"role": "assistant", "content": "Teams are focusing on evals, tool routing, and observability."},
    ],
)
```

## Multimodal inputs

Attach images to the current message with `attachments`:

```python theme={null}
result = client.invoke_agent(
    agent="vision-agent",
    message="Describe this image",
    attachments=["https://example.com/photo.jpg"],
)
print(result["response"])
```

URLs must start with `https://`.

## Configuration

| Option     | Default                        | Description                     |
| ---------- | ------------------------------ | ------------------------------- |
| `api_key`  | `FETCH_HIVE_API_KEY` env var   | Bearer token from the dashboard |
| `base_url` | `https://api.fetchhive.com/v1` | Override the API base URL       |
| `timeout`  | `120`                          | Request timeout in seconds      |

```python theme={null}
client = FetchHive(
    api_key="fhk_...",
    base_url="https://api.fetchhive.com/v1",
    timeout=120,
)
```

## Errors

Non-2xx responses raise an `httpx.HTTPStatusError` with the status code and response body:

```python theme={null}
import httpx

try:
    reply = client.invoke_agent(agent="AGENT_UUID", message="Hello")
except httpx.HTTPStatusError as exc:
    print("Fetch Hive returned", exc.response.status_code, exc.response.text)
```

See [Errors and Rate Limits](../api-reference/errors-and-rate-limits) for status code meanings.

## Links

* [Package on PyPI](https://pypi.org/project/fetch-hive-sdk/)
* [Source on GitHub](https://github.com/Fetch-Hive/python-sdk)

## Next steps

* [Run with API](./run-with-api) - The same flow with cURL
* [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)
* [Invoke Agent](../api-reference/agents/invoke) - Full endpoint reference
