Skip to content

About

Proxy that captures and visualizes in-flight Anthropic and Openai requests and conversations.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

Agent Context Probe

Agent Context Probe Demo

Agent Context Probe is a local proxy and Dashboard for inspecting Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses traffic. The production build is one Go executable: the React Dashboard is compiled as a SPA and embedded in the binary.

The default command is:

agent-context-probe start

The proxy, management API, health check, and Dashboard share http://127.0.0.1:3001.

Features

  • Transparent Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses proxying
  • Streaming and non-streaming response capture
  • First generated stream content timestamp and proxy-observed TTFT in request history
  • SQLite request history with model, time, and header filters
  • Session and parent/subagent trace views
  • Agent framework integrations for Codex, OpenCode, Claude Code, LangChain/LangGraph, OpenAI Agents SDK, AutoGen, and CrewAI
  • Normalized messages, reasoning, tool calls, tool results, token usage, and latency
  • Grouped namespace tool definitions (including Codex MCP and multi-agent tools) with full parameter schemas
  • Optional Claude Code subagent routing to different upstream models
  • Optional downstream response fault injection for harness testing
  • One executable with an embedded Dashboard; Node.js is not required at runtime
  • Local-only listening by default
  • Sensitive request and response headers redacted before SQLite persistence
  • Explicit token authentication for non-loopback listening

Codex SDK session traces

Codex SDK requests (typically Originator: codex_sdk_ts) are grouped by Thread-Id, so each agent retains its own model-call timeline even when parent and child agents share Session-Id. X-Codex-Parent-Thread-Id links each child to its direct parent, including nested subagents. Child threads without a task tool-call association are displayed separately within the parent trace.

Identity headers are matched case-insensitively, using the first non-empty value in this order: Thread-Id, X-Thread-Id, X-Session-Affinity, X-OpenCode-Session, X-Claude-Code-Session-Id, Session-Id, X-Session-Id, then X-Conversation-Id. Without any identity header, each request remains separate. Shared Session-Id alone does not establish a direct parent relationship; threads whose parent is absent from the captured history are shown as roots. Existing stored headers are used when loading session views, so previously captured requests benefit without a database migration.

History reconstructed from the first captured request preserves the original order of user prompts and tool calls. Consecutive user messages, such as Codex context followed by task instructions, are displayed together as one turn. Assistant messages and tool results separate genuine follow-up turns.

For streaming model responses, the stored response includes firstTokenAt (RFC 3339 timestamp) and ttftMs (milliseconds from the proxy handler's request start to the first completed SSE data line with generated text, reasoning, or tool-call content). Metadata, usage, empty deltas, and terminal events do not count. These fields are absent when no generated content is observed, including non-streaming responses. The timing reflects arrival at this proxy, not delivery to the client.

Build from source

Building requires Go 1.21 or later and Node.js 20 or later. The resulting executable does not require Go, Node.js, npm, or a separate SQLite library.

macOS and Linux

git clone https://github.com/2proveit/agent-context-probe.git
cd agent-context-probe
make install
make build
./bin/agent-context-probe start

./run.sh performs the build and start sequence as a convenience.

Windows

Run in PowerShell:

git clone https://github.com/2proveit/agent-context-probe.git
Set-Location agent-context-probe
powershell -NoProfile -ExecutionPolicy Bypass -File .\run.ps1

The script builds bin\agent-context-probe.exe and starts the single process.

Install a Release

Release archives contain the executable, configuration example, README, LICENSE, and install/uninstall scripts. On macOS and Linux:

./scripts/install.sh --version 0.1.0-beta.1
export PATH="$HOME/.local/bin:$PATH" # if the installer reports it is missing
agent-context-probe version

On Windows:

.\scripts\install.ps1 -Version 0.1.0-beta.1
agent-context-probe.exe version

Running the installer again atomically replaces the executable and preserves configuration, request history, and backups. The uninstall scripts remove only the executable; user data is retained. The Windows installer adds its install directory to the user PATH and the Windows uninstaller removes that exact entry.

CLI

agent-context-probe start [--config FILE] [--data-dir DIR] [--host HOST] [--port PORT]
agent-context-probe doctor [--config FILE] [--data-dir DIR] [--host HOST] [--port PORT]
agent-context-probe version

Running the executable without a subcommand remains equivalent to start.

doctor validates the resolved configuration, embedded Dashboard, data directory, database schema, and listen address without contacting an upstream provider or modifying files. Run it while the service is stopped so it can test the configured port.

Standard user directories

System Configuration Request database and backups
macOS ~/Library/Application Support/Agent Context Probe/config.yaml ~/Library/Application Support/Agent Context Probe/
Linux ${XDG_CONFIG_HOME:-~/.config}/agent-context-probe/config.yaml ${XDG_DATA_HOME:-~/.local/share}/agent-context-probe/
Windows %APPDATA%\Agent Context Probe\config.yaml %LOCALAPPDATA%\Agent Context Probe\

No configuration file is created automatically. The data directory is created on first start. The application no longer discovers .env, parent-directory configuration files, or a current-directory requests.db; source checkouts can keep the legacy layout by using ./run.sh, run.ps1, --config, --data-dir, or DB_PATH explicitly.

Use the proxy

Start Agent Context Probe, then open the Dashboard:

http://127.0.0.1:3001/

For Claude Code or another Anthropic-compatible client:

export ANTHROPIC_BASE_URL=http://127.0.0.1:3001
claude

PowerShell equivalent:

$env:ANTHROPIC_BASE_URL = "http://127.0.0.1:3001"
claude

For an OpenAI-compatible client, use this local API prefix:

http://127.0.0.1:3001/v1

Available endpoints:

  • POST /v1/messages
  • POST /v1/chat/completions
  • POST /v1/responses
  • GET /v1/models: requests with an anthropic-version or x-api-key header forward to providers.anthropic.base_url + /v1/models, preserving x-api-key and filling in a missing anthropic-version from configuration. Other requests (including Bearer-only requests) forward to providers.openai.base_url + /models. If the selected provider has no custom base URL and the other provider does, the request falls back to the other provider. Empty base URLs and the built-in defaults (ignoring surrounding whitespace and trailing slashes) count as unconfigured; when both or neither are configured, header routing is retained. Both branches preserve the upstream status and body and capture the request/response for the dashboard. Upstream connection failures return 502.
  • GET /health
  • GET /api/requests
  • DELETE /api/requests
  • GET /api/sessions
  • GET /api/ui-config

The removed /api/grade-prompt frontend route had no Go implementation and is not part of the supported API.

Security model

The default host is 127.0.0.1. Cross-origin access is not enabled: the Dashboard calls the Go API on the same origin.

The proxy forwards the original client credentials to the selected upstream, subject to existing provider rules. A configured OPENAI_API_KEY replaces the incoming OpenAI Authorization value for the upstream request. The stored copy is separate: values for headers such as Authorization, Proxy-Authorization, Cookie, Set-Cookie, and X-Api-Key are replaced with [REDACTED] before being written to SQLite or returned by the management API. On startup, existing rows are also migrated to remove those stored header values.

Selected configuration files, SQLite databases, and backups use mode 0600 on Unix-like systems. Newly created data and backup directories use mode 0700.

Non-loopback listening

Listening on 0.0.0.0, ::, or a LAN address requires an access token of at least 16 characters. Configure it through ACP_ACCESS_TOKEN or server.access_token:

ACP_HOST=0.0.0.0 \
ACP_ACCESS_TOKEN='replace-with-a-long-random-value' \
agent-context-probe start

Remote API clients must send the token in X-Agent-Context-Probe-Token. This control header is removed before proxying and is never sent to an upstream provider. Browser users are redirected to /auth; successful login creates an HttpOnly, SameSite=Strict session cookie. Use a TLS reverse proxy when traffic crosses an untrusted network.

Configuration

Copy config.yaml.example to config.yaml when file-based configuration is needed:

server:
  host: "127.0.0.1"
  port: 3001
  timeouts:
    read: 15m
    write: 15m
    idle: 15m

providers:
  anthropic:
    base_url: "https://api.anthropic.com"
    version: "2023-06-01"
    max_retries: 3
  openai:
    base_url: "https://api.openai.com/v1"
    # api_key: "prefer OPENAI_API_KEY"

storage:
  # Omit db_path to use the operating system standard data directory.
  # db_path: "/custom/path/requests.db"
  # backup_dir: "/custom/path/backups"
  max_capture_bytes: 10485760

web:
  show_raw_stream_events: false
  raw_request_max_display_chars: 0
  raw_response_max_display_chars: 0

Configuration value priority is command-line override, environment variable, configuration file, then built-in default. Configuration file selection is --config, then ACP_CONFIG, then the standard configuration path. Database selection is --data-dir, then DB_PATH, then ACP_DATA_DIR, then storage.db_path, then the standard data directory. Relative paths in YAML are resolved from the selected configuration file directory.

Environment variables:

Variable Purpose
ACP_CONFIG Explicit configuration file path
ACP_DATA_DIR Data directory used when DB_PATH is unset
ACP_HOST Listen host; defaults to 127.0.0.1
ACP_PORT Listen port; defaults to 3001
PORT Backward-compatible port alias
ACP_ACCESS_TOKEN Required for non-loopback listening
READ_TIMEOUT Go duration such as 30s or 15m
WRITE_TIMEOUT Go duration
IDLE_TIMEOUT Go duration
ANTHROPIC_FORWARD_URL Anthropic upstream base URL
ANTHROPIC_VERSION Anthropic API version
ANTHROPIC_MAX_RETRIES Anthropic retry count
OPENAI_BASE_URL OpenAI-compatible upstream API prefix
OPENAI_API_KEY Optional upstream OpenAI key
DB_PATH SQLite database path

storage.max_capture_bytes limits retained OpenAI request and response bytes; it does not truncate the proxied exchange. The raw display limits affect only Dashboard rendering and not the stored value.

SQLite capture operations share one connection to serialize in-process writes. Each connection waits up to 3 seconds for an external database lock; a final capture failure is logged with the request ID. Large history reads or exports can delay queued captures. This does not change the configured database path, schema, or forwarded response bytes.

Downstream response fault injection

Optional response_corruption simulates malformed responses from self-hosted models, inference frameworks, gateways, or middleware to test a harness's validation, recovery, and fallback behavior. It supports all three generation APIs (JSON and SSE), with faults such as empty output, repetition, invalid tool calls, and stream truncation. Upstream requests are unchanged.

Disabled by default. Add this to your configuration and restart the proxy:

response_corruption:
  enabled: true
  every_n_requests: 1
  seed: 42
  modes: [empty_stop]

empty_stop removes visible text and tool calls. every_n_requests: 1 selects every eligible HTTP 200 generation response; set it to 3 for every third eligible response. Upstream errors are excluded. Set enabled: false and restart after testing.

SQLite stores provider responses before injection; inspect harness-side raw responses to see the injected faults. See the fault injection reference for all modes, selection rules, capture behavior, and validation steps, or config.yaml.example for the full configuration.

Database schema upgrades

SQLite schema versions are recorded with PRAGMA user_version. A database whose schema is newer than the executable is rejected to prevent downgrade writes. When an existing database requires an upgrade, Agent Context Probe:

  1. removes persisted sensitive header values;
  2. creates a consistent SQLite backup under the configured backup directory;
  3. validates the backup with PRAGMA quick_check;
  4. applies all pending migrations in one transaction.

Backup files are never deleted automatically. doctor reports the current and target schema without performing the migration.

Model mappings

Set model_mappings in config.yaml to replace exact incoming model names:

model_mappings:
  claude-sonnet: deepseek-v4-flash
  gpt-4o: custom-openai-model

Mappings apply to Anthropic Messages, OpenAI Chat Completions, and OpenAI Responses requests. The proxy changes only the upstream request's model value; a model mapping never changes the selected provider. Ordinary Anthropic requests use providers.anthropic.base_url; OpenAI requests use providers.openai.base_url. Existing subagent routing may select a different provider before the model mapping is applied. Mappings are exact and applied once. Successful JSON and streaming responses report the client's original model name, while request records retain both originalModel and routedModel.

Optional subagent routing

subagents:
  enable: true
  mappings:
    code-reviewer: "gpt-4o"
    deep-reasoning: "o3"

Mappings are applied only when the matching Claude Code subagent definition is available. Unmapped models continue through the normal provider selection.

Docker

The runtime image contains one process and one exposed port. It has no Node.js runtime or node_modules.

docker build -t agent-context-probe .
docker run --rm \
  -p 3001:3001 \
  -e ACP_ACCESS_TOKEN='replace-with-a-long-random-value' \
  -v ./data:/app/data \
  agent-context-probe

The container listens on 0.0.0.0, so the access token is mandatory. Open http://127.0.0.1:3001/ and enter the same token. API clients must send the control header described above. SQLite data is stored at /app/data/requests.db by default.

Coding agent skill

The reusable agent-context-probe skill guides coding agents through proxy setup, session identity, API-based evidence collection, stream/tool-call diagnosis, and explicitly requested fault tests.

Point an agent at skills/agent-context-probe/SKILL.md, or copy the complete skills/agent-context-probe/ folder into that agent's supported skill directory. A repository-root skills/ folder is not automatically discovered by every agent. For example: “Read /path/to/agent-context-probe/skills/agent-context-probe/SKILL.md and use it to investigate my captured agent session.”

Development

make install
make build       # SPA build, asset synchronization, then Go build
make dev         # build and start the single process
make run-proxy   # build the SPA and run the Go process through go run
make run-web     # optional Vite development server with /api proxying
make clean
make db-reset

Release validation:

goreleaser check
goreleaser release --snapshot --clean --skip=publish

Pushing a v* tag triggers .github/workflows/release.yml. The workflow builds the tag artifacts once without publishing, tests those exact archives through install/start/upgrade/uninstall without Go, Node.js, or npm in PATH, then uploads the same files to the GitHub Release and publishes the linux/amd64 plus linux/arm64 GHCR image. Archives include SHA-256 checksums and SPDX JSON SBOMs; GitHub generates provenance attestations for release artifacts and the container image.

Validation commands:

cd proxy && go test ./...
cd ../web && npm run typecheck && npm test
cd ../web && npm run lint && npm run build

Type checking, tests, lint, and the production SPA build are separate checks; run them independently when diagnosing an existing codebase violation.

Project structure

agent-context-probe/
├── proxy/
│   ├── cmd/agent-context-probe/  # CLI entry point
│   └── internal/
│       ├── app/                  # application composition and lifecycle
│       ├── buildinfo/            # injected version, commit, and build time
│       ├── capture/              # persistence redaction policy
│       ├── handler/              # protocol and management handlers
│       └── webui/                # embedded SPA and fallback handler
├── web/                          # React/Vite SPA source
├── Dockerfile                    # single-process runtime image
├── Makefile
├── run.ps1
└── run.sh

Acknowledgements

Agent Context Probe was originally derived from seifghazi/claude-code-proxy and has since evolved into an independently maintained project.

We thank Seif Ghazi and the original contributors for their work. The original project and Agent Context Probe are distributed under the MIT License. See LICENSE for the applicable copyright and license notices.

License

MIT License. See LICENSE.

About

Proxy that captures and visualizes in-flight Anthropic and Openai requests and conversations.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages