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

# Configuration

> Configuration options and advanced features

# Configuration

## Environment variables

All variables use the `SWARMD_` prefix by default.

| Variable                | Required    | Default                                                              |
| ----------------------- | ----------- | -------------------------------------------------------------------- |
| `SWARMD_AGENT_ID`       | Yes         | —                                                                    |
| `SWARMD_CLIENT_SECRET`  | Yes         | —                                                                    |
| `SWARMD_WEBHOOK_SECRET` | Recommended | —                                                                    |
| `SWARMD_BASE_URL`       | No          | `https://api.swarmd.ai`                                              |
| `SWARMD_TOKEN_URL`      | No          | `https://auth.swarmd.ai/realms/swarmd/protocol/openid-connect/token` |
| `SWARMD_TIMEOUT`        | No          | `30` (seconds)                                                       |
| `SWARMD_MAX_RETRIES`    | No          | `3`                                                                  |

`SWARMD_WEBHOOK_SECRET` is the HMAC-SHA256 key SwarmD uses to sign **inbound** webhooks delivered to your agent's `/admin/webhook` endpoint. Without it, your agent still works for outbound calls — but it won't receive automatic kicks when a subscription is created/removed, an agent is registered/deregistered/frozen/unfrozen, or its tenant is frozen/unfrozen. You'd need to call `/admin/refresh` manually after each platform event.

Returned **once** at agent registration alongside `clientSecret`; store both with your agent's deployment configuration. Lost secrets can only be recovered by deregistering and re-registering the agent (which rotates both).

### Custom prefix

If you run multiple agents in the same process, use different prefixes:

```python theme={null}
weather = SwarmDClient.from_env("WEATHER_AGENT")
calendar = SwarmDClient.from_env("CALENDAR_AGENT")
```

```bash theme={null}
WEATHER_AGENT_AGENT_ID=...
WEATHER_AGENT_CLIENT_SECRET=...
WEATHER_AGENT_WEBHOOK_SECRET=...
CALENDAR_AGENT_AGENT_ID=...
CALENDAR_AGENT_CLIENT_SECRET=...
CALENDAR_AGENT_WEBHOOK_SECRET=...
```

### Sandbox environment

Point to the sandbox by overriding the base and token URLs:

```bash theme={null}
SWARMD_BASE_URL=https://api.sandbox.swarmd.ai
SWARMD_TOKEN_URL=https://auth.sandbox.swarmd.ai/realms/swarmd/protocol/openid-connect/token
```

## Agent Directory

`AgentDirectory` maintains a background-refreshed, snapshot-isolated list of your agent's subscriptions. It's useful for long-running services that need an up-to-date view of available downstream agents.

| Parameter          | Type           | Default | Description                               |
| ------------------ | -------------- | ------- | ----------------------------------------- |
| `client`           | `SwarmDClient` | —       | Authenticated client instance             |
| `agent_id`         | `UUID`         | —       | Your agent's UUID                         |
| `refresh_interval` | `float`        | `60`    | Seconds between background refreshes      |
| `on_change`        | `Callable`     | `None`  | Callback when agents are added or removed |

```python theme={null}
from swarmd_sdk import SwarmDClient, AgentDirectory
from uuid import UUID

client = SwarmDClient.from_env()
agent_id = UUID("your-agent-uuid")

# Refresh every 30 seconds instead of the default 60
with AgentDirectory(client, agent_id, refresh_interval=30) as directory:
    # Lookup an agent by name
    weather = directory.get("weather_agent")
    if weather:
        print(weather.agent_card_url)

    # Iterate all agents
    for agent in directory.agents:
        print(agent.name)
```

Key behaviors:

* **Snapshot isolation** — The agent list is an immutable tuple. Background refreshes swap the reference atomically, so in-flight tasks always see a consistent snapshot.
* **Change callbacks** — Pass `on_change` to be notified when agents are added or removed:

```python theme={null}
def on_change(added, removed):
    for agent_id in added:
        print(f"New agent: {agent_id}")
    for agent_id in removed:
        print(f"Agent removed: {agent_id}")

directory = AgentDirectory(client, agent_id, on_change=on_change)
```

## SwarmDConfig

For programmatic configuration without environment variables:

```python theme={null}
from swarmd_sdk import SwarmDClient, SwarmDConfig

config = SwarmDConfig(
    agent_id="your-agent-id",
    client_secret="your-client-secret",
    webhook_secret="your-webhook-secret",
    base_url="https://api.sandbox.swarmd.ai",
    timeout=60,
    max_retries=5,
)

client = SwarmDClient.from_config(config)
```

## Models

### AgentResponse

Returned by `get_agent_subscriptions()`.

| Field            | Type   | Description                                                |
| ---------------- | ------ | ---------------------------------------------------------- |
| `agent_id`       | `UUID` | Agent's unique identifier                                  |
| `name`           | `str`  | Display name                                               |
| `description`    | `str`  | Agent capabilities description                             |
| `agent_card_url` | `str`  | URL to the agent's A2A card (proxied through SwarmD relay) |

## Exceptions

| Exception             | When                    | Attributes                     |
| --------------------- | ----------------------- | ------------------------------ |
| `SwarmDSDKError`      | Base exception          | `message`, `cause`             |
| `AuthenticationError` | OAuth2 auth failures    | `message`, `cause`             |
| `TokenRefreshError`   | Token acquisition fails | `message`, `cause`             |
| `APIError`            | HTTP request failures   | `status_code`, `response_body` |
