> This page is for version dev.
> For other versions, use one of these documentation indexes:
> - Latest (v1.5.1) (default): https://docs.nvidia.com/dynamo/latest/llms.txt
> - dev: https://docs.nvidia.com/dynamo/dev/llms.txt
> - v1.5.1: https://docs.nvidia.com/dynamo/v1.5.1/llms.txt
> - v1.5.0: https://docs.nvidia.com/dynamo/v1.5.0/llms.txt
> - v1.4.2: https://docs.nvidia.com/dynamo/v1.4.2/llms.txt
> - v1.4.1: https://docs.nvidia.com/dynamo/v1.4.1/llms.txt
> - v1.4.0: https://docs.nvidia.com/dynamo/v1.4.0/llms.txt
> - v1.3.0: https://docs.nvidia.com/dynamo/v1.3.0/llms.txt
> - v1.2.1: https://docs.nvidia.com/dynamo/v1.2.1/llms.txt
> - v1.2.0: https://docs.nvidia.com/dynamo/v1.2.0/llms.txt
> - v1.1.1: https://docs.nvidia.com/dynamo/v1.1.1/llms.txt
> - v1.1.0: https://docs.nvidia.com/dynamo/v1.1.0/llms.txt
> - v1.0.2: https://docs.nvidia.com/dynamo/v1.0.2/llms.txt
> - v1.0.1: https://docs.nvidia.com/dynamo/v1.0.1/llms.txt
> - v1.0.0: https://docs.nvidia.com/dynamo/v1.0.0/llms.txt
> - v0.9.1: https://docs.nvidia.com/dynamo/v-0-9-1/llms.txt
> - v0.9.0: https://docs.nvidia.com/dynamo/v-0-9-0/llms.txt
> - v0.8.1: https://docs.nvidia.com/dynamo/v-0-8-1/llms.txt
> - v0.8.0: https://docs.nvidia.com/dynamo/v-0-8-0/llms.txt
> - v0.7.1: https://docs.nvidia.com/dynamo/v-0-7-1/llms.txt
> - v0.7.0: https://docs.nvidia.com/dynamo/v-0-7-0/llms.txt

> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.nvidia.com/dynamo/llms.txt. For full content including API reference and SDK examples, see https://docs.nvidia.com/dynamo/llms-full.txt.

# Agent Harnesses

Dynamo exposes `v1/chat/completions`, `v1/responses`, and `v1/messages`, so any agent that uses these APIs can talk to a Dynamo endpoint even if it is not listed in this guide. This guide focuses on popular agent harnesses that send stable session IDs. Dynamo normalizes these IDs for tracing and other explicitly configured consumers.

On Chat Completions and Responses requests, function tools with explicit `strict: true` receive schema preflight before inference. Invalid schemas now return HTTP 400 where earlier versions could accept them. Responses validates every submitted function, including namespace members and functions excluded by `allowed_tools` or `tool_choice: "none"`. Omitted, `null`, or `false` strictness and omitted or `null` parameters retain existing behavior.

Preflight runs independently of structural-tag activation. Passing preflight does not guarantee complete OpenAI compatibility or backend enforcement. See [Request Validation](/dynamo/dev/parsing/structural-tag#request-validation) for object rules, size budgets, and Dynamo's bounded local-reference support.

#### Start a local agent endpoint

To locally test these out, we have a small script that runs an SGLang-backed `zai-org/GLM-4.7-Flash` endpoint. This script starts a TP2 instance on port 8000 and enables request tracing for replay and visualization. By default traces are saved in `/tmp/dynamo-request-trace-$(date +%Y%m%d-%H%M%S)`

To start it, run:

```bash
bash examples/backends/sglang/launch/agg_agent.sh
```

#### Configure a harness

#### Codex

Codex uses the Responses API. Add a local provider in `~/.codex/config.toml`:

```toml
[model_providers.dynamo]
name = "dynamo"
base_url = "http://localhost:8000/v1"
wire_api = "responses"
```

Dynamo's Responses adapter currently supports function tools, including functions inside namespaces, and `tool_choice` values of `none`, `auto`, `required`, or a named function. Unsupported tool or tool-choice types return HTTP 400 before inference. Unsupported tools are rejected even when `tool_choice` is `none` or `auto`.

Disable Codex's hosted web search when using Dynamo. The following command overrides the top-level `web_search` setting for this run:

```bash
# replace -m <model> with your model
codex -m zai-org/GLM-4.7-Flash -c model_provider=dynamo \
  -c 'web_search="disabled"'
```

Dynamo maps Codex's `thread-id` header to `session_id`. A spawned child thread also sends `x-codex-parent-thread-id`, which Dynamo maps to `parent_session_id`.

#### Pi

Pi uses the Dynamo provider plugin. Build and install it from the [agent-plugins](https://github.com/ai-dynamo/agent-plugins/tree/main/pi-plugin) checkout:

```bash
git clone https://github.com/ai-dynamo/agent-plugins.git ~/agent-plugins
cd ~/agent-plugins/pi-plugin
npm install && npm run build
pi install "$PWD"
```

Point it at the Dynamo OpenAI-compatible endpoint and run Pi with the `dynamo` provider:

```bash
export DYNAMO_BASE_URL=http://localhost:8000/v1
export DYNAMO_API_KEY=dynamo-local

pi --model dynamo/zai-org/GLM-4.7-Flash
```

#### Claude Code

Claude Code uses the Anthropic-compatible Messages API. The local launcher above starts `dynamo.frontend` with `--enable-anthropic-api`; for other deployments, pass that flag when starting the frontend. Then set:

```bash
export ANTHROPIC_BASE_URL=http://localhost:8000
export ANTHROPIC_MODEL=zai-org/GLM-4.7-Flash
export ANTHROPIC_SMALL_FAST_MODEL=zai-org/GLM-4.7-Flash
export CLAUDE_CODE_ATTRIBUTION_HEADER=0 # preserve KV cache hits
export ANTHROPIC_API_KEY=

claude
```

Dynamo uses `x-claude-code-session-id` as the Claude Code session ID. For subagents, Dynamo uses `x-claude-code-agent-id` as the child session ID. Nested subagents use `x-claude-code-parent-agent-id` as the parent; top-level subagents fall back to the root session ID.

#### OpenCode

OpenCode uses a project-local JSONC provider config; setting an endpoint environment variable alone is not enough. Create `.opencode/opencode.jsonc` in the project where you run OpenCode:

```jsonc
{
  "provider": {
    "dynamo": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Dynamo",
      "models": {
        "zai-org/GLM-4.7-Flash": {
          "id": "zai-org/GLM-4.7-Flash",
          "name": "GLM 4.7 Flash"
        }
      },
      "options": {
        "baseURL": "http://localhost:8000/v1"
      }
    }
  },
  "permission": {
    "task": "allow"
  }
}
```

Run OpenCode with the provider/model pair:

```bash
opencode -m dynamo/zai-org/GLM-4.7-Flash
```

Dynamo maps OpenCode's `x-session-id` header to `session_id` and `x-parent-session-id` to `parent_session_id`.

#### OpenClaw

OpenClaw can use Dynamo through its OpenAI-compatible Responses endpoint. Install the Dynamo provider plugin:

```bash
git clone https://github.com/ai-dynamo/agent-plugins.git ~/agent-plugins
openclaw plugins install --link ~/agent-plugins/openclaw-plugin
openclaw plugins enable dynamo
```

Add a Dynamo-backed model to `~/.openclaw/openclaw.json`:

```jsonc
{
  "models": {
    "providers": {
      "dynamo": {
        "baseUrl": "http://localhost:8000/v1",
        "apiKey": "dynamo-local",
        "api": "openai-responses",
        "models": [
          {
            "id": "zai-org/GLM-4.7-Flash",
            "name": "Dynamo GLM 4.7 Flash",
            "reasoning": true,
            "contextWindow": 128000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "dynamo/zai-org/GLM-4.7-Flash"
      }
    }
  }
}
```

Run OpenClaw:

```bash
openclaw chat
```

The plugin copies OpenClaw's current `sessionId` into `x-dynamo-session-id` on each request. Native subagents receive their own `session_id`, and the immediate parent is recorded as `parent_session_id`.

#### Hermes Agent

Hermes uses an OpenAI-compatible custom endpoint. Configure Hermes with the served model name and Dynamo `/v1` base URL:

```yaml
model:
  default: zai-org/GLM-4.7-Flash
  provider: custom
  base_url: http://localhost:8000/v1
  api_mode: chat_completions
```

If your Dynamo endpoint requires authentication, add `api_key: <token>` to the Hermes model config or set `OPENAI_API_KEY`.

This configuration lets you run Hermes with the `hermes` command. To send session IDs to Dynamo, install the plugin:

```bash
# clone the plugin
git clone https://github.com/ai-dynamo/agent-plugins.git ~/agent-plugins
# link it to where Hermes typically looks for plugins
ln -sfnT ~/agent-plugins/hermes-plugin ~/.hermes/plugins/dynamo_session
hermes plugins enable dynamo_session

# run Hermes
hermes
```

The plugin copies the Hermes `session_id` into `x-dynamo-session-id` on each LLM request.

## Drive a Harness from Another Agent

Use the repository's `.agents/skills/dynamo-agent-harness` skill when an agent needs to keep a Claude Code, Codex, or OpenCode session open across multiple prompts while Dynamo serves the model. The skill uses Agent Client Protocol (ACP) and injects the provider configuration through the child process environment instead of adding harness configuration files to the delegated worktree.

The skill pins the Claude Code and Codex ACP adapters. If a harness release changes the model, endpoint, session header, authentication, or mode configuration, update this page and the skill in the same change after running a persistent two-turn tool smoke test.

## Agent Headers

Dynamo carries raw coding-agent HTTP headers in `AgentContext.agent_headers` without interpreting them. Capture includes the open `x-claude-code-*` and `x-codex-*` families alongside supported session and subagent headers. Names within those families are not hardcoded: new headers are captured without a Dynamo schema change. Header names and values can change as coding harnesses evolve. Plugin authors and trace consumers own any parsing or normalization between harnesses.

Names are lowercase. Values remain strings, including malformed JSON, percent encoding, whitespace, empty values, and repeated values in their received order. Core code only normalizes session identity and the explicit Dynamo terminal marker.

Capture requires a recognized session identity and is bounded to 64 header values, 16 KiB per value, and 32 KiB total, counting the name once per value. Sensitive-marked and non-text values are skipped. Values exceeding the limits are omitted whole; retained values are never truncated. Missing metadata means no observation was captured, not that an event did not occur. Ordinary authentication, cookie, and unrelated protocol headers are excluded. Do not place credentials in an agent metadata header; these values are exposed to plugins and request traces.

The map travels through the frontend and worker request envelope and is available through plugin `SessionContext.agent_headers()`. It contains HTTP headers only; request-body metadata is not captured. The default routing policy does not interpret the map. See [Agent Tracing](/dynamo/dev/agents/agent-tracing#dynamo-request_end-record) for the request-trace format and [Custom Worker Selection](/dynamo/dev/knowledge-base/modular-components/router/write-custom-routing-strategies#session-context) for plugin access.

For Claude Code custom endpoints, enable gateway hints with `CLAUDE_CODE_GATEWAY_HINT_HEADERS=1`. Its [gateway protocol](https://code.claude.com/docs/en/llm-gateway-protocol#gateway-hint-headers) defines the header semantics. Preserving observations in `AgentContext` does not implement transparent Anthropic request-body or header forwarding to upstream providers.

## See Also

* [Session IDs](/dynamo/dev/agents/session-i-ds)
* [Agent Tracing](/dynamo/dev/agents/agent-tracing)
* [SGLang for Agentic Workloads](/dynamo/dev/knowledge-base/modular-components/backends/sg-lang/agents-on-sg-lang)