Skip to main content

Local-first CLI for handing coding sessions between agents without losing context

Project description

Agent Relay

PyPI Downloads Buy Me A Coffee

Agent Relay is a local-first CLI for handing work from one coding agent to another without losing context, decisions, or validation state.

It is built for the moment when one agent needs to stop because of rate limits, tool limits, or a manual handoff. Agent Relay captures a structured checkpoint, renders an immutable resume packet, and records the launch/resume flow in a repo-local session journal.

Built-in agent adapters currently support Claude Code and Codex.

Why use it

  • keep one durable session history across multiple agent handoffs
  • capture checkpoints with decisions, blockers, touched files, and validation state
  • render agent-specific resume packets from the latest checkpoint
  • preview or execute a prepared launch command
  • recover and inspect session state from on-disk journal data

Installation

Python 3.11 or newer is required.

macOS / Linux

curl -fsSL https://agent-relay.dev/install.sh | sh

Windows (PowerShell)

irm https://agent-relay.dev/install.ps1 | iex

Already using uv or pipx?

uv tool install agent-relay-tool   # or: pipx install agent-relay-tool

Full per-OS walkthroughs and verification steps: agent-relay.dev/installation.

Quick start

Run the CLI inside the repository whose work you want to hand off:

cd /path/to/your/repo

# One-command relay: hand off to another agent
agent-relay codex --task "Continue the release prep"

# Single-agent managed run (best for handoffs — see Best Practices)
agent-relay run c "Fix the failing tests"

# Turn-based conversation between agents
agent-relay chat c x "Fix the failing tests"

# Concurrent agents working simultaneously (tmux)
agent-relay race c x "Build the auth module"

# Resume the latest unresolved concurrent conflict
agent-relay resolve --latest

# Inspect saved conflict artifacts
agent-relay inspect-conflicts <session-id>

# See what agents are available
agent-relay discover

# View sessions
agent-relay status

# Live view of an in-progress session (auto-picks newest active)
agent-relay watch

# Token / cost / duration rollup for a session
agent-relay metrics

Agent aliases: c = Claude, x = Codex. Use agent-relay discover to see all available agents and aliases.

Best practices

Start inside Relay for the strongest handoffs

The single most important thing you can do for better handoffs is start the work inside Relay instead of only calling Relay after an agent stops.

When Relay manages the session from the beginning, it runs the agent in --print mode and captures the full output stream — including the agent's reasoning, tool calls, decisions, and structured state. This means the handoff packet contains everything the next agent needs: recent conversation history, the current plan, blockers, remaining work, intended edits, and any provider-exported session state.

When Relay joins after the fact, it can only hand off what is still observable: the working tree changes, any notes you provide, and whatever the provider can export at that moment. Private reasoning, in-progress drafts, and tool-call history from an unmanaged session are lost.

In simple terms: if Relay was there while the work was happening, handoffs are much stronger. If Relay joins later, it can only hand off what it can still see.

Use run as the default starting point

agent-relay run c "Fix the failing tests"

run is the recommended way to start any single-agent task when you know a handoff might happen later. It:

  • runs the agent with live output capture (reasoning, tool calls, decisions)
  • extracts structured state from each turn (status, remaining work, blockers)
  • stores full turn artifacts (prompt, output, stderr, state) for later recovery
  • builds continuation context automatically so the next agent picks up exactly where this one left off

If the agent finishes the work, great. If it hits a rate limit or needs to hand off, the session already has everything Relay needs to produce a strong resume packet.

Use chat for multi-agent collaboration

agent-relay chat c x "Fix the failing tests"

chat runs agents in alternating turns. Each agent sees the full conversation history — what every other agent said, decided, and proposed. Use this when agents need to build on each other's work iteratively, like one agent investigating and another implementing.

Use race for parallel work with enforced delegation

agent-relay race c x "Build the auth module"

race is a phased concurrent workflow, not just two agents launched side by side. It enforces a structured process:

  1. Planning: every agent must claim a concrete slice of work before implementation begins.
  2. Implementation: each agent works inside its own isolated git worktree, so changes cannot collide during execution.
  3. Merge and review: Relay only merges in-scope work back to the main repo.
  4. Conflict handling: Relay saves conflict artifacts, can run an automatic resolver/reviewer pass, and hands off to resolve when human judgment is still needed.

Fall back to one-command relay when Relay was not managing the session

agent-relay codex --task "Claude hit its limit; continue from the current state"

If an agent was working outside of Relay and needs to hand off, open a new terminal in the same repo and run a one-command handoff. Relay will capture what it can (git changes, any notes you provide) and generate a packet for the target agent. This is less complete than a managed session but still far better than starting from scratch.

What Relay can recover

When Relay managed the session (run, chat, race)

  • full conversation turn history (prompts, outputs, reasoning)
  • structured state from each turn (status, plan, blockers, remaining work)
  • intended and proposed edits (even if not yet applied)
  • provider-exported session state when available
  • current working tree changes
  • verification items and validation results

When Relay joins after the fact (one-command handoff)

  • current working tree changes (git diff)
  • planning notes you provide via --planning-note-file
  • proposed edits you provide via --proposed-edits-file
  • anything the provider can export at handoff time

What Relay cannot recover

  • private hidden reasoning from an unmanaged session
  • UI-only drafts that were never saved anywhere
  • proposed edits shown in a tool UI but never accepted, exported, or passed to Relay

Commands

Primary commands

Command Description
agent-relay run <agent> <task> Single-agent managed session with live capture. Best starting point for any task.
agent-relay chat <agents...> <task> Turn-based agent conversation. Agents alternate with full history context.
agent-relay race <agents...> <task> Concurrent workflow with planning, isolated worktrees, and conflict recovery (tmux).
agent-relay <agent> One-command relay to a target agent. Creates packet and optionally launches.

Conflict resolution

Command Description
agent-relay resolve [session-id] Resume unresolved race conflicts.
agent-relay resolve --latest Resume the most recent unresolved conflict.
agent-relay inspect-conflicts <session-id> Inspect saved conflict artifacts, versions, and resolution hints.

Session management

Command Description
agent-relay discover Show available agents, aliases, and CLI paths.
agent-relay status List all relay sessions in the current repo.
agent-relay watch [session-id] Live TUI of an in-progress session. Auto-picks newest active when no id is given. --json streams JSONL events; --quiet streams one terse line per event; --no-follow prints a single snapshot and exits. Add --metrics for a token / cost / duration panel.
agent-relay metrics [session-id] Token / cost / latency rollup for a session. Use --all for cross-session totals, --since YYYY-MM-DD to filter, --agent claude (repeatable) to scope.
agent-relay metrics-tail [session-id] Stream metric events as JSONL — one line per turn_completed, plus a final session rollup. Optional --webhook URL POSTs each line.
agent-relay metrics-serve Run a metrics exporter. --prometheus :9464 exposes /metrics in Prometheus text format; --otlp http://collector:4318/v1/metrics pushes OTLP/HTTP-JSON every 30s. Both can run together.
agent-relay clean Remove all sessions. Use --all to remove entire .agent-relay/ directory.

Options

Option Description
--task, -t Task for agents (alternative to positional argument)
--continue Continue from a prior relay session id
-n Max turns for run/chat (default: 10)
--max-time Max seconds for race (default: 600)
--open-terminals Auto-open terminal windows/tabs for race/resolve on macOS
--no-open-terminals Disable auto-open terminal behavior
--from Source agent for relay (auto-detected by default)
--no-launch Create the handoff packet without launching the target agent
--yes, -y Skip confirmation prompt
--json Machine-readable JSON output
--quiet, -q Minimal output

Recommended workflows

Single-agent task with potential handoff

# Start inside Relay for the strongest handoff later
agent-relay run c "Fix the failing tests"

# If the agent hits a limit, the session is already captured.
# Hand off to another agent:
agent-relay codex --task "Continue from the saved session"

Turn-based collaboration

# Two agents alternating
agent-relay chat c x "Fix the failing tests"

# Three agents, 6 turns max
agent-relay chat c x c "Review and fix" -n 6

Live monitoring of a running session

While a session is in flight, open a second terminal in the same repo and run:

# Auto-pick the newest active session
agent-relay watch

# Or pin to a specific session
agent-relay watch <session-id>

# Stream events as JSONL — pipe into other tools
agent-relay watch --json | jq -c '{ts: .timestamp, kind: .kind}'

# Print a single snapshot of current state and exit
agent-relay watch --no-follow

The live TUI surfaces journal events, workspace activity, the current turn's elapsed time and progressive agent output, and the latest turn state — all in real time. The watcher exits cleanly when the session reaches a terminal status (completed, ready_for_handoff) or on Ctrl-C.

Add --metrics for a token / cost / duration panel that refreshes after every turn:

agent-relay watch --metrics

Cost & performance metrics

Relay computes metrics on read — no extra files in .agent-relay/, no cache invalidation. The same data backs four surfaces:

# Per-session table (auto-picks the most recent session)
agent-relay metrics

# Cross-session aggregates: by agent, by day, totals
agent-relay metrics --all
agent-relay metrics --all --since 2026-05-01 --agent claude

# Machine-readable
agent-relay metrics --json
agent-relay metrics --quiet      # one TSV line per session

# Live JSONL stream — one line per turn_completed plus a final session rollup
agent-relay metrics-tail
agent-relay metrics-tail --webhook https://hooks.example.com/relay

Cost is best-effort. If an agent output includes an actual total_cost_usd style field, Relay uses it. Codex exec --json normally emits token usage but not a billed cost, so Relay estimates Codex cost from the captured model name. Managed Codex turns save the model from the JSON stream when available, then fall back to AGENT_RELAY_CODEX_MODEL, CODEX_MODEL, OPENAI_MODEL, or $CODEX_HOME/config.toml. Uncached input tokens, cached input tokens, and output tokens are priced separately. Estimates do not include account discounts, Batch/Flex or priority processing, data residency uplift, long-context uplift, or separately billed tool fees.

For dashboards and long-running collection, metrics-serve runs an exporter:

# Prometheus pull-based scrape endpoint (stdlib only)
agent-relay metrics-serve --prometheus :9464
# → curl http://localhost:9464/metrics

# OTLP push to a collector (HTTP/JSON, every 30s by default)
agent-relay metrics-serve --otlp http://localhost:4318/v1/metrics

# Both can run together
agent-relay metrics-serve --prometheus :9464 --otlp http://localhost:4318/v1/metrics

Metrics emitted (Prometheus naming; OTLP uses dotted equivalents):

Metric Type Labels
agent_relay_tokens_total counter agent, direction (input, output, cache_read, cache_creation)
agent_relay_cost_usd_total counter agent
agent_relay_turn_duration_ms_sum / _count summary agent
agent_relay_turns_total counter agent, result (success, error)
agent_relay_session_active gauge
agent_relay_sessions_total gauge status

Alerts

Threshold-based alerts ride the metrics-tail channel. They are opt-in — no config file, no alerts. Drop a .agent-relay/config/alerts.toml:

cost_per_turn_usd = 0.50
cost_per_session_usd = 5.00
duration_per_turn_ms = 300000
tokens_per_turn = 200000
error_rate_threshold = 0.4    # ratio 0..1; gated by error_rate_min_turns
error_rate_min_turns = 5

When a turn breaches a threshold, metrics-tail writes a colored line to stderr and emits an extra JSONL line on stdout:

{
  "kind": "metrics.alert",
  "rule": "cost_per_turn",
  "severity": "warning",
  "session_id": "...",
  "turn_number": 3,
  "threshold": 0.5,
  "observed": 0.71,
  "message": "turn 3 cost $0.7100 exceeds threshold $0.5000",
  "timestamp": "..."
}

Severity is critical at ≥ 2× threshold, warning otherwise. Webhook delivery (when --webhook is set) carries alert lines too, so external systems can react without polling.

Concurrent work with conflict recovery

# Start a concurrent run
agent-relay race c x "Build the auth module"

# Continue an interrupted or timed-out concurrent session
agent-relay race --continue <session-id> c x "Continue the task"

# Inspect saved conflict artifacts and versions
agent-relay inspect-conflicts <session-id>

# Resume unresolved conflict resolution
agent-relay resolve <session-id>
agent-relay resolve --latest

Claim roles in race:

  • owner: exclusive editor for that path or directory
  • shared: multiple agents may edit that scope intentionally
  • reviewer: review-only overlap; edits in reviewer-only scope are blocked

Notes:

  • On macOS, Relay can auto-open one terminal window or tab per tmux session. Use --open-terminals or --no-open-terminals to control that behavior explicitly.
  • If a concurrent run ends in manual_resolution_required, use inspect-conflicts first to see the saved versions, then resolve to continue the resolution workflow.
  • If a concurrent run ends in max_time, interrupted, incomplete, or agent_error, use race --continue <session-id> ... to continue the broader task.

Preserve planning-only work

If there are no file changes yet, pass the planning and proposed-edit context explicitly:

agent-relay codex \
  --task "Continue from the saved plan" \
  --planning-note-file handoff-notes/planning.md \
  --proposed-edits-file handoff-notes/proposed.diff \
  --no-launch

This is the best fallback when an agent did useful planning but did not write code to disk.

Configuration

Capture helpers

Variable Description
AGENT_RELAY_AUTOSAVE_GIT_TOUCHED_FILES=1 Auto-save git diff of touched files
AGENT_RELAY_AUTOSAVE_RESEARCH_NOTE_FILE=<path> Auto-capture research notes
AGENT_RELAY_AUTOSAVE_IMPLEMENTATION_NOTE_FILE=<path> Auto-capture implementation notes
AGENT_RELAY_AUTOSAVE_VALIDATION_SUMMARY_FILE=<path> Auto-capture validation summary
AGENT_RELAY_AUTOSAVE_PLANNING_SNAPSHOT_FILE=<path> Auto-capture planning snapshot
AGENT_RELAY_AUTOSAVE_PROPOSED_EDITS_FILE=<path> Auto-capture proposed edits

Launch template overrides

Variable Description
AGENT_RELAY_CLAUDE_LAUNCH_TEMPLATE Custom launch command for Claude
AGENT_RELAY_CODEX_LAUNCH_TEMPLATE Custom launch command for Codex

Capture hook templates

Variable Description
AGENT_RELAY_CLAUDE_CAPTURE_TEMPLATE Custom capture hook for Claude exports
AGENT_RELAY_CODEX_CAPTURE_TEMPLATE Custom capture hook for Codex exports

Template placeholders

Available in both launch and capture templates:

Placeholder Description
{agent} Agent key (e.g. claude)
{agent_name} Display name (e.g. Claude Code)
{agent_cli} Shell-quoted CLI command
{repo_root} Shell-quoted repo root path
{repo_root_path} Unquoted repo root path
{resume_path} Shell-quoted path to resume packet
{resume_path_path} Unquoted path to resume packet
{session_id} Session identifier

Built-in defaults

claude: cd {repo_root} && claude -p "$(cat {resume_path})"
codex:  cd {repo_root} && codex "$(cat {resume_path})"

Custom launch templates must include {resume_path} or {resume_path_path}. If a template omits the packet input, launch --execute refuses to run it.

Capture templates are optional. If set, they should print JSON to stdout with any of these fields:

  • resumable_state
  • planning_snapshot
  • proposed_edits
  • transcript
  • session_metadata
  • warnings

Storage model

Agent Relay writes repo-local state under .agent-relay/.

Each session lives under .agent-relay/sessions/<session-id>/ and uses a journal-plus-objects layout:

  • session.json: immutable session manifest
  • journal/: append-only event log
  • objects/checkpoints/<checkpoint-id>/: checkpoint manifests, summaries, repo-state captures, and related artifacts
  • objects/handoffs/<handoff-id>/: resume packet, packet hash, and launch specification
  • objects/launches/<launch-id>/: launch receipts and captured stdout/stderr
  • refs/head.json: latest derived head pointer
  • derived/view.json: current materialized session view
  • recovery/: pending transactions, quarantine, and repair reports
  • turns/<turn-number>/: turn artifacts from run/chat sessions (prompt, output, stderr, state)

This keeps the session state inspectable and vendor-independent.

What not to publish

Do not commit or publish .agent-relay/. Session artifacts can contain:

  • absolute local paths
  • research notes and implementation notes
  • validation summaries
  • captured Git status, workspace patches, and untracked-file manifests
  • generated resume packets
  • rendered launch commands and launch-template text
  • full agent conversation output (from run/chat sessions)

Two practical rules:

  • add .agent-relay/ to .gitignore
  • do not put secrets or tokens into AGENT_RELAY_CLAUDE_LAUNCH_TEMPLATE or AGENT_RELAY_CODEX_LAUNCH_TEMPLATE, because the rendered command and template are recorded in handoff metadata

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_relay_tool-0.6.0.tar.gz (251.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_relay_tool-0.6.0-py3-none-any.whl (281.1 kB view details)

Uploaded Python 3

File details

Details for the file agent_relay_tool-0.6.0.tar.gz.

File metadata

  • Download URL: agent_relay_tool-0.6.0.tar.gz
  • Upload date:
  • Size: 251.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for agent_relay_tool-0.6.0.tar.gz
Algorithm Hash digest
SHA256 c35e880dad8dfba06dbe66ca31b02bd89702faebc655ee7cb23dac0b5b0193c1
MD5 aa85a1a754d5846439613b28e0b939c1
BLAKE2b-256 c4d1a8ec3d5fd7bb21e0decbd0bedd531407471adcd2dacb165fa765c41af4d6

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_relay_tool-0.6.0.tar.gz:

Publisher: publish.yml on bethvourc/agent-relay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_relay_tool-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_relay_tool-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0556e52a8ae9d61377c7650221fb3bc2cd8bf94878a2f81c47f0c990f94600e7
MD5 d18d1e5b52270e68f5ddc18b4cc7a28f
BLAKE2b-256 f7dd6da37da3dacea732a456aa8ccb29e31f77923633f8b629154bd63f7dd74f

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_relay_tool-0.6.0-py3-none-any.whl:

Publisher: publish.yml on bethvourc/agent-relay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page