Observed since 20 Oct, 21:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Terminal-native agent runtime with persistent sessions, branching, and MCP
Terminal-native agent runtime built on the OpenAI Agents SDK and MCP.
Persistent sessions. Branching conversations. Multi-provider. Local-first.
# Recommended: isolated install (like pipx, but faster)
uv tool install agenterm
# Or try without installing
uvx agenterm --help
# Or traditional pip
pip install agenterm
After installation, run:
agenterm --version # verify installation
agenterm repl # start interactive session
agenterm’s local toolset wraps external CLI binaries. If any are missing, the CLI fails fast with an install hint.
brew install ripgrep fd bat tree
stat is provided by the OS (BSD/GNU); ensure it is available on PATH.
On non‑macOS platforms, install the same binaries via your system package
manager and ensure they are on PATH.
agenterm runs inside any project directory and provides:
agenterm repl — start an interactive REPL session (prompts to save config if missing).agenterm run — execute a one‑shot run (prompt args, --file, or piped stdin).agenterm inspect — inspect background responses (response), local runs (run), run event ledgers (run-events), SDK turns (turn), or agent_run reports (agent-run).agenterm config — create and view effective configuration (save, show, path).agenterm agents — view/manage agents (instruction files) (list, show, path, save).agenterm mcp — diagnostics, inspection, and MCP server exposure.agenterm artifacts — browse durable artifacts produced by the agent.agenterm session — introspection and management of local Agents sessions.agenterm branch — manage session branches (list/use/new/fork/delete/runs).The engine is a single‑path pipeline:
CLI / REPL → AppConfig + SessionState → Agents engine (Responses + tools + MCP) → output
For product vision and target architecture, see VISION.md and ARCH.md.
This README focuses on how to use the CLI.
For contributing or running from source:
Install dependencies:
uv sync
Initialize configuration (first-time setup):
Option A (recommended): start the REPL and save a config when prompted.
uv run agenterm repl
Option B (non-interactive): write a baseline config explicitly.
uv run agenterm config save --scope global
Use --force to overwrite an existing ~/.agenterm/config.yaml.
Optional: create a per-project override:
uv run agenterm config save --scope local
Optional: write baseline agent files:
uv run agenterm agents save --scope global
Run the CLI:
uv run agenterm --help
Ensure credentials are available:
openai/... models: set OPENAI_API_KEY in your shell environment, or
run agenterm repl and use /config key <KEY> to save it to ~/.agenterm/.env.gateway/... models: set the env vars referenced by
providers.gateway.routes.*.api_key_env (local backends like built-in
gateway/ollama/* may omit keys).The runtime dependencies (Agents SDK, OpenAI client, MCP types) live in .venv and are treated as the runtime source of truth for types and behavior.
agenterm uses command-scoped flags. Put flags after the subcommand name:
uv run agenterm run --model openai/gpt-5.2-pro --config path/to/config.yaml "..."
Common flags:
--config PATH (-c) — select a config file (commands that load config).--format human|json (-o) — select output format per command (--format json emits a single JSON envelope).--model ID (-m) — override the configured model (openai/<model> or gateway/<route>/<model>).--agent NAME — override the configured agent name (commands that resolve agent files, like run, repl, and agents show/path).--no-retry/--retry — disable/enable provider retries for this run.--max-retries N — override provider transport/status retry count for this run.--deadline-seconds T — override provider total retry deadline for this run.--attempt-timeout-seconds T — override provider per-attempt timeout for this run.--quiet (-q) — suppress informational notices.--verbose (-v) — show verbose error details.--version (-V) — show the CLI version and exit.agenterm run "...")Basic usage:
uv run agenterm run "describe this repo"
Foreground runs always stream internally. By default (quiet), the CLI prints only the final answer and footer. With --live, the CLI prints tool calls/outputs and reasoning labels as they arrive. Background runs are the only non‑streaming mode.
agenterm run never prompts. Approvals are auto‑resolved and short config/agent source notes are emitted to stderr. Use the REPL for interactive approvals or config/agent save prompts.
Input can come from:
--file FILE (-f),stdin — used only when no other source is provided.Foreground runs support two orthogonal toggles:
--live:
--live):
[reasoning], [tool call], [tool output] as they arrive and renders the final answer with Markdown.--format json):
agenterm <command> --format json … to force machine‑readable JSON output for that command.{schema_version, trace_id, ts, result:{resource, payload}} (see ARCH.md).--live is set (JSON mode emits exactly one document).Defaults for --live / JSON output come from run.live and run.json_output in config.yaml (--format overrides per invocation).
When a run is cancelled mid‑turn, agenterm records in‑flight turn items and automatically prepends them to the next run input.
Properties:
function_call without
a matching function_call_output for the same call_id, agenterm appends a
synthetic function_call_output error envelope
(kind="recovered_missing_tool_output") before provider submission so replay
stays coherent and provider requests remain valid.REPL shortcut:
/continue starts a new run with no new user message and relies on the automatic
resume mechanism (use /again to re-send the full previous prompt).Attach local files or URLs to a run invocation:
uv run agenterm run \
--attach path/to/file.py \
--attach https://example.com/spec.pdf \
"summarize these"
agenterm supports OpenRouter via an OpenAI-compatible Responses API gateway route. This proof run demonstrates:
input_image) via an inline data URL.export OPENROUTER_API_KEY="..." # required
uv run agenterm run \
--config examples/config/openrouter_gemini3_proof.yaml \
--tool fn:inspect \
--attach examples/assets/expression.jpeg \
"Describe the image, then call the inspect tool."
Notes:
--tool fn:inspect restricts the tool surface to a single safe local tool.
Combined with model.tool_choice: required in the example config, the model must
emit at least one tool call.attachments.allow_inline_data_url: true),
so local images are sent to the provider as data:<mime>;base64,... in input_image.image_url.
Disable this policy if you only want to attach public URLs (no local file ingestion).agenterm ships a built-in ollama gateway route:
gateway/ollama/<model>http://localhost:11434/v1api_key_env: null)allow_any_model: true (local model ids vary by machine)Quick start:
# Start Ollama and ensure a model is available.
ollama serve
ollama pull gpt-oss:20b
# Run through the built-in route.
uv run agenterm run --model gateway/ollama/gpt-oss:20b "summarize this repository"
Notes:
OPENAI_API_KEY is not required for gateway/ollama/* runs.Enable tools (file search, web_search (web.run), local tool inspect,
agent_run, agent_run_report, apply_patch, plan, image_generation, and sandboxed shell on macOS/Linux)
as follows:
config.yaml (see “Configuration”).tools.bundles and tools.default_bundles in config.yaml to control which tools and MCP servers are active.--tools-bundle NAME (repeatable) to select bundle names.--tool KEY (repeatable) to select individual tool keys.--no-tools).agent.max_turns (SDK turns per run, 1–500) in config.yaml.
MaxTurnsExceeded; completed SDK turns remain in session history.
Start a new run or raise agent.max_turns to continue.Dangerous is a tool label used for gating (not a tool family). Defaults are policy-driven but can be overridden in config.
Default dangerous refs:
fn:shell, fn:apply_patch, fn:user:*, mcp:*hosted:mcp:*plan, agent_run_report, safe read tooling (inspect),
and agent_run are safe by default (no side effects).Overrides (config):
tools.dangerous.add: force‑mark tool refs as dangerous.tools.dangerous.remove: force‑mark tool refs as safe.
web_search (web.run) dangerous or mark apply_patch safe.Tool ref syntax:
hosted:openai:web_search for web_search/web.run, fn:shell, mcp:files)file_search, web_search (web.run), image_generation, inspect, shell, apply_patch,
plan, agent_run_report, steward, agent_run)fn:user:<name> or fn:user:*hosted:mcp:<name> or hosted:mcp:*mcp:<server_key> or mcp:*Behavior:
--allow-dangerous, dangerous tools are dropped from selection.agenterm run never prompts. Use the REPL for interactive approvals.prompt mode (manual) and are handled via a modal approvals overlay.--approvals auto starts the session in auto mode.agenterm does not attempt to classify arbitrary shell strings as “read-only”.
Platform notes:
fn:shell is available on macOS and Linux via OS-enforced sandbox backends.fn:apply_patch is cross-platform, but is confined to the workspace root and always goes through approvals.You can drive structured JSON outputs via a JSON/YAML schema configured in config.yaml:
uv run agenterm config save --scope local
${EDITOR:-vi} .agenterm/config.yaml
uv run agenterm run "answer using this schema"
Set model.text_format_file in your config to point at a schema file (for example examples/structured/answer_schema.yaml). This loads a JSON/YAML schema into model.text_format and installs a structured output schema so the model emits responses that follow your JSON schema.
Structured output schemas are enforced in strict mode: object schemas are normalized to include
additionalProperties: false, and invalid schemas fail fast before any request is sent.
Consolidated trace flag:
--trace on|off — enable/disable tracing for this invocation--trace ID:GROUP:key=val,... — all-in-one trace configuration (implicitly enables tracing)These map into the following fields in AppConfig.run:
run.trace_enabledrun.trace_idrun.group_idrun.trace_metadataThey are forwarded to the Agents RunConfig so your observability backend can correlate CLI runs and REPL sessions. The REPL /status command surfaces the active tracing configuration.
Quick lookup (non-REPL):
agenterm trace show — display effective trace configuration (--format json for scripts).Use --background to submit a server‑side (non‑streaming) run:
uv run agenterm run --no-tools --background "run this in the background"
Behavior:
The run command prints only a response_id for background submissions:
response_id: resp_...
Background mode is accepted only for:
openai/<model>, andgateway/<route>/<model> where the route is configured with
protocol: openai_responses and supports_background: true.Built-in route defaults:
gateway/openrouter/*: background disabled (supports_background: false)gateway/ollama/*: background disabled (supports_background: false)Background runs only attach hosted-plane tools (hosted:*).
All client-plane tools (fn:*, mcp:*, fn:user:*) are stripped automatically in background mode (background runs cannot reach your local machine), including local MCP servers.
Hosted MCP connectors can be used in background mode by selecting:
hosted:mcp:<name> (from mcp.connectors[*].name),--allow-dangerous when the connector is marked dangerous
(default: hosted MCP connectors are dangerous; overrideable via tools.dangerous.remove).Use agenterm inspect response to inspect a previously submitted background response:
uv run agenterm inspect response RESPONSE_ID
# Include one page of canonical server-side input items:
uv run agenterm inspect response RESPONSE_ID --input-items --input-items-limit 20 --input-items-order desc
Scope:
inspect response is OpenAI-credentialed (OPENAI_API_KEY) and does not
retrieve gateway route response IDs.This fetches a single Responses object by id and prints:
response_idbackground: true when the run was submitted with --backgroundcompleted, failed)in=… out=… total=… tokens)output: block with aggregated text output--input-items), including pagination metadata:
--input-items-after ITEM_ID--input-items-limit N (1..100)--input-items-order asc|descThis path is strictly read‑only:
--background runs easy to inspect without leaving the CLI.Local inspection reads the SQLite store and does not require provider access:
uv run agenterm inspect run SESSION_ID 3
uv run agenterm inspect run-events SESSION_ID 3
uv run agenterm inspect turn SESSION_ID 7
To inspect delegated agent_run reports (stored as artifacts):
uv run agenterm inspect agent-run REPORT_ID
Every one-shot agenterm run invocation uses a local SQLite-backed session (AgentermSQLiteSession, an agenterm-owned wrapper around Agents AdvancedSQLiteSession) so transcripts and usage are persisted in a shared SQLite store.
By default, each run creates a fresh session with a UUID session_id.
To reuse a session across multiple runs and continue from local session history (SDK turns), pass:
uv run agenterm run --session <UUID> "continue this agent in the same session"
--session <UUID> is resume-or-fail: if the session does not exist locally, agenterm exits with an error. Use agenterm session list to discover valid ids.
To target a specific branch within a session, use --branch <BRANCH_ID> (defaults to the session head branch):
uv run agenterm run --session <UUID> --branch main "continue on a branch"
To override the server-side store per run (without editing config), use
--store/--no-store:
uv run agenterm run --store "enable server-side store for this run"
Default is model.store: false (provider store off). Set model.store: true to
enable server-side persistence by default.
Use the session subcommands to inspect stored transcripts and usage:
agenterm session list — list sessions in the local store (compact table with single-line last-message previews).agenterm session show <ID> — print metadata; includes usage_total when the per-request ledger is present.agenterm session runs <ID> [--branch <BRANCH_ID>] — show run history for a branch; tokens include cached/reasoning totals when available.agenterm branch list <SESSION_ID> — list branches for a session.agenterm repl)Start the REPL:
uv run agenterm repl
Input defaults:
Core commands:
/help [topic] — tiered help; shows overview or per-command details./status — session snapshot (model, tools, config, IDs)./errors — show captured stderr/logging lines from the REPL error buffer./last diff [preview|full] — show the most recent apply_patch diff (preview is line‑bounded; full is unbounded)./last tools [preview|full] — show the most recent tool call/output (bounded preview by default; full is explicit)./last approvals [preview|full] — show the most recent approvals (pending + resolved; includes rejection reasons)./trace [show|clear|on|off] — tracing controls for this session./quit — exit REPL (also Ctrl+D).
Model and tools:
/model — route-first model picker (modal).
openai, openrouter, ollama).model_suggestions) plus discovered route catalog entries./model <route> — open the picker directly for one route (openai|openrouter|ollama)./model <ID> — set model directly (openai/<model> or gateway/<route>/<model>)./model gpt-5.2 is treated as openai/gpt-5.2 in the REPL./tools [sub] — view and adjust tool bundles and individual tools./approvals [sub] — manage tool approvals (mode: prompt|auto; supports list|show|approve|reject)./resilience [show] — print effective provider retry policy for the active model
(provider defaults, route overrides, resolved budget, streamed restart paths).Settings (consolidated under /config):
/config key <KEY> — set API key for this session./config verbosity [low|medium|high|unset] — adjust output detail./config reasoning [effort|summary] <VALUE> — adjust reasoning effort/summary.REPL UI controls (/repl):
/repl theme dark|light — select the REPL prompt theme.
/repl color-depth auto|mono|ansi|default|truecolor — set prompt-toolkit color depth (default auto, which picks the highest supported depth; truecolor on macOS Terminal/iTerm2)./repl mouse on|off — enable/disable mouse support in the prompt UI (default on)./repl completion off|commands|full — toggle completion (slash commands only, or slash + history suggestions)./repl edit-mode emacs|vi — set editing mode (vi default, emacs optional).UX toggles (/ux):
/ux markdown on|off — toggle styled Markdown rendering for agent output./ux reasoning off|summary — show/hide reasoning summaries (summary-only; no chain-of-thought dumps)./ux diffs off|summary — show/hide apply_patch diff artifacts in the transcript./ux stream final|live — choose final-only vs live text streaming (Markdown renders only in final mode)./ux verbosity quiet|normal|debug — control detail level (labels-only → bounded details → raw event types).Session management (consolidated under /session):
/session new — start a fresh REPL conversation./session list — list known sessions in the local SQLite store (compact table with single-line last-message previews)./session use <ID> — attach to an existing stored session./session runs [N] — show recent runs for the current session.
Branch management (consolidated under /branch):
/branch list — list branches for the current session./branch use <BRANCH_ID> — switch to a branch./branch new [BRANCH_ID] — create a new branch from head and switch to it./branch fork <RUN_NUMBER> [BRANCH_ID] — create a branch from a run (exclusive) and switch to it./branch delete <BRANCH_ID> [--force|-f|force] — delete a branch (never main; deleting current branch requires force)./branch runs [N] — show recent runs for the active branch.
Context and control:
/attach <PATH|URL> — stage files/URLs for the next run (e.g., /attach README.md)./attach list — show staged and last-used attachments./attach remove <PATH|URL>|all — unstage attachments for the next run (does not reset conversation)./attach clear — clear staged attachments and cancel any pending “use last attachments” state./agent — show the current agent./agent list — list available agents./agent <NAME> — switch agent and branch from head (e.g., /agent agenterm)./compress — run compression and switch to the compression continuation (snapshot/compaction, provider‑dependent); tracked as a run in the session ledger./compress show — print the latest compression continuation (snapshot/compaction), grouped by content/citation type; UI-only output with binary payloads redacted./mcp refresh|status — refresh MCP servers or show status/tool counts./again — re-run the last prompt; forks from the last run when it has turns, otherwise retries in place (requires a stored session)./continue — continue after cancellation/timeout without resending the full previous prompt (uses automatic resume)./edit — edit the last prompt; forks from the last run when it has turns, otherwise edits in place (requires a stored session)./ux stream final|live. Live mode streams plain text deltas (no panels); final mode renders the completed answer (Markdown when enabled).AppConfig / Agents engine as run./model picker and approvals). Approvals still emit transcript decision blocks.AUTO in bold danger red when approvals mode is automatic.>. Approval posture is shown in the HUD/placeholder notice.agent: <name>[model] | effort: <value> | tools: <bundle> | context: <percent>% where <percent> uses provider-reported
input tokens for the last provider request of the last completed run, normalized by model.context_window when configured;
when model.context_window is null, the toolbar shows the raw token count (packing uses a 128k token fallback internally).AUTO appears when approvals mode is auto (right-aligned when width permits, otherwise appended).agenterm session runs --branch … / agenterm session show <SESSION_ID> (token ledger).
This is informational and does not change model behavior.Tool approvals in the REPL are non‑blocking:
shell or apply_patch tool call requires approval, the model run runs as a background task while the UI stays responsive.[approval requested] transcript block.
[approved] / [rejected] blocks appear when the decision resolves.y/yes in the modal input to approve the next pending tool call.n/no with an optional trailing reason (n <reason...>) to reject (forwarded to the model).y/n decision, the approvals modal closes immediately when no approvals remain pending./approvals list and /approvals show <ID> to inspect details on demand./last approvals to inspect the most recent approval requests and decisions (bounded; includes rejection reasons)./approvals auto to approve everything pending and continue without prompts./approvals prompt to return to manual approvals.run:
/approvals auto enables auto‑approval for the session.repl.approvals.mode: auto in config starts REPL sessions in auto‑approval mode.--attach PATH|URL (repeatable).--file FILE,stdin (when no other source is provided).Under the hood, agenterm maps prompts and attachments into Responses input items based on provider capabilities (file_id, image_url, file_url).
Attachment mapping:
{"type":"message","role":"user","content":[{"type":"input_text","text":"..."}]}.
/continue is the only path that sends no new user message (input=[]).input_text (inline text).http(s) URL
(or inline data URLs when explicitly allowed).http(s) URL
(or inline data URLs when explicitly allowed).http(s) URLs map to input_image.image_url for images or input_file.file_url for other files.input_image.image_url and input_file.file_data (file IDs/URLs are rejected).attachments.*.Example assets in examples/assets/:
examples/assets/agents_guide.pdf — long-form document for testing file search/attachments.examples/assets/expression.jpeg — math expression image for vision tests
(prompt: "simplify this expression").Examples are runnable demos and test assets. Canonical behavior and contracts live
in README.md and ARCH.md. Reference-only material lives in docs/ref/.
See docs/ref/README.md for the reference index.
See examples/README.md for the full examples index.
Reference input-item example: docs/ref/response-input-example.yaml.
agenterm reads a single config.yaml into an AppConfig (see ARCH.md). Discovery order:
--config PATH (explicit)..agenterm/config.yaml (project-local override; when present).~/.agenterm/config.yaml (global baseline; Linux and macOS only).Use agenterm config save --scope global to create the global baseline config,
agenterm config save --scope local to create a per-project override, or
agenterm config path to see the active config location.
If no config file exists yet, agenterm runs with a fully-typed built-in default
AppConfig. The REPL offers a one-time prompt to save a config, while
agenterm run stays non-interactive and prints a short config-source note on stderr.
In greenfield mode, any config/agent file validation error is fatal; the CLI
instructs you to delete the local/global .agenterm/ directories and retry.
The agent name is the filename (without extension) for the instruction file. There is no separate display name — the agent name is used everywhere.
agenterm resolves the active agent from the highest‑priority source available.
Local agent files override global ones, and REPL /agent overrides everything
for the active session.
On agenterm agents save, bundled agents are copied to:
~/.agenterm/agents/ # global defaults
./.agenterm/agents/ # project-local overrides
Local saves prefer copying global agents when they exist.
agenterm agents show prints the full effective agent file:
--plain for raw text.--format json for a single JSON envelope.Use agenterm agents path to report the effective source + path.
Starter instruction templates live in docs/ref/agent-instruction-templates.md
(reference-only); adapt them to your repo constraints.
Resolution order:
--agent NAME (CLI explicit override)./.agenterm/agents/<name>.md project-local override (when present)~/.agenterm/agents/<name>.md user default (if it exists and is readable)src/agenterm/data/agents/<name>.md shipped with the packageIn the REPL, /agent <NAME> switches agents and creates a new branch from
head (unless there is no session history yet, in which case the current branch metadata
is updated in place); this live override is the highest priority within that
session.
The default agenterm agent is a generalist companion tuned for local,
tool-using work. The bundled coding_agent agent establishes:
Edit ~/.agenterm/agents/<name>.md to customize agent behavior globally, or
./.agenterm/agents/<name>.md to customize it per-project.
AppConfig schema (see agenterm config save), so it always stays in sync with the code.config.yaml, while agent files live in .agenterm/agents/ (local/global overrides):
Retries are configured centrally in retries within config.yaml. SDK‑internal retries are
disabled; agenterm’s own retry policy is the single source of truth. Use:
retries.provider for model calls (streamed/background/agent_run).retries.mcp for MCP list_tools / call_tool retries.retries.store for SQLite SQLITE_BUSY backoff.Provider resilience uses one shared run budget across retry-like paths:
max_retries — transport/status retries inside the provider retry loop.max_total_attempts — total provider attempts allowed across all retry-like loops.deadline_seconds — max wall time for the full provider operation (attempts + backoff).attempt_timeout_seconds — max wall time per provider attempt.For one-shot runs, override provider resilience per invocation with:
--no-retry, --max-retries, --deadline-seconds, and
--attempt-timeout-seconds.
model.store) controls provider persistence only:
model.store: false).--store or --no-store.last_response_id is stored per branch only when provider storage is enabled
(for inspection identifiers, not for continuity).Session history (SDK turns) and usage are persisted locally via the Agents session store:
AgentermSQLiteSession (an agenterm-owned wrapper around Agents AdvancedSQLiteSession) backed by the history DB at ~/.agenterm/<version>/history.sqlite3.run and repl keep full transcripts without requiring additional configuration files.~/.agenterm/<version>/store.sqlite3 to support post‑mortem debugging.Some model/tool outputs are too large to store directly in session history (SDK turns) (base64 image payloads). agenterm treats these as durable artifacts:
~/.agenterm/<version>/history.sqlite3~/.agenterm/<version>/store.sqlite3~/.agenterm/artifacts/~/.agenterm/artifacts/images/<artifact_id>.<ext>image_generation_call.result: null; rehydration is UI‑only and never re‑injects base64 into model input./artifacts list [N], /artifacts show <ID>, /artifacts open <ID>, /artifacts agent-run <ID>,
/inspect agent-run <ID> [--json]agenterm artifacts list|show|open|agent-run
agenterm artifacts list supports --session-id and --trace-id filters.agenterm run ... prints image artifact cards even in quiet mode.agenterm run --format json ... includes result.payload.artifacts so scripts can capture paths deterministically.Compression runs before a run and may also run mid-run (between model turns) when the packed input grows too large. This is most common in multi-turn agent loops or when tool output expands the prompt.
Compression creates a compression continuation branch (snapshot/compaction) and switches head; subsequent model calls replay from the continuation and stay local.
For snapshot compression, reasoning items are excluded from the compressor payload (no reasoning content/summaries/encrypted reasoning fields are forwarded).
Snapshot contract (canonical):
Steward structured output is strict ContinuationCapsule JSON
(state, open, pending, next, integrity).
Snapshot compressor input is a single user message envelope:
<agent_instructions>...</agent_instructions><base_continuation>...</base_continuation> (exact previous capsule JSON)<delta>...</delta> (JSON array of transcript messages since baseline)Snapshot continuation injection is one user message with two text parts:
next.action).<continuation>\n{CAPSULE_JSON}\n</continuation>/compress show renders a human summary of the latest continuation (it does not print the
raw capsule JSON).Compression preserves protocol coherence: if a pending function_call has no
matching function_call_output, agenterm preserves a tail from that pending call
forward and inserts the continuation message before the tail.
Strategy:
snapshot: run steward.snapshot (continuation snapshot).compaction_if_supported: use /responses/compact when the provider declares support; fall back to snapshot otherwise.both_if_supported: run both snapshot + compaction and select the active continuation branch via primary_branch.Trigger:
ask: prompt in the REPL only; non‑REPL runs skip compression unless trigger: auto.auto: run compression without prompting.Threshold:
compression.threshold_percent (0 < x ≤ 1).model.context_window (default 200000) as the reference budget; the threshold is capped
by the input token budget (context_window - max_output_tokens).Drop policy:
deny: refuse to drop turns after compression (default).ask: prompt before dropping turns.allow: drop oldest turns without prompting when still over budget.Example:
compression:
# snapshot | compaction_if_supported | both_if_supported
strategy: compaction_if_supported
# ask | auto
trigger: auto
# Compress when history reaches 50% of the context window.
threshold_percent: 0.5
# When running both snapshot + compaction, which continuation branch becomes active.
primary_branch: snapshot
# deny | ask | allow
drop_policy: deny
Example config file: examples/config/compression_percent.yaml
Gateway route example: examples/config/gateway_routes.yaml
Ollama route example: examples/config/ollama_local.yaml
AppConfig in code)agent:
# Model identifier (Responses/Agents models only).
# Model IDs are prefixed: openai/<model> or gateway/<route>/<model>.
# Validation uses provider registries
# (OpenAI /models cache + optional OpenAI allowlist policy,
# or gateway route policy: allowlist/allow_any_model).
model: openai/gpt-5.2
# Agent name (instruction file name; bundled agents live in src/agenterm/data/agents).
# Use /agent <NAME> in the REPL to switch and branch from head.
name: agenterm
# SDK turn limit per run (1–500).
max_turns: 250
model:
# Sampling
temperature: 1.0
#top_p: 0.9
#frequency_penalty: 0.0
#presence_penalty: 0.0
# Output length (visible + reasoning tokens where applicable)
max_output_tokens: 64000
# Reasoning defaults are optimized for GPT-5.
# OpenAI non-GPT-5 models require reasoning: null.
# Gateway routes map reasoning by protocol (Responses vs LiteLLM).
reasoning:
effort: xhigh
summary: auto
# Model verbosity (maps to Responses text.verbosity)
# low|medium|high
verbosity: medium
# Include usage so the CLI can surface token summaries.
include_usage: true
# Advanced knobs (map directly to ModelSettings / Responses):
tool_choice: auto
# agenterm always disables provider-level tool parallelism (parallel_tool_calls=false).
truncation: disabled
store: false
context_window: 200000 # default tokens; set null for 128k fallback; manual; for packing + UI %
prompt_cache_retention: 24h # or "in_memory"
# Optional per-request metadata forwarded to the model API.
#metadata:
# run_id: demo-123
# Structured output (JSON schema). When set, this populates model.text_format and installs
# a structured output schema so the model emits responses that follow your JSON schema.
#text_format:
# type: json_schema
# name: example_answer
# schema:
# type: object
# properties:
# summary:
# type: string
# description: Short natural-language summary of the result.
# required: ["summary"]
# additionalProperties: false
# strict: true
# description: Example structured answer format
#
# Alternatively, you can point at a JSON/YAML schema file. Exactly one of
# text_format/text_format_file may be set.
#text_format_file: examples/structured/answer_schema.yaml
#top_logprobs: 0
#extra_headers:
# X-Experiment: B
#extra_query:
# service_tier: priority
#extra_body:
# metadata:
# run_id: demo-123
providers:
openai:
# Optional OpenAI-compatible endpoint override (e.g., Azure).
# When set, this overrides OPENAI_BASE_URL.
base_url: null
# Route-first picker defaults for direct OpenAI models.
model_suggestions:
- gpt-5.2
- gpt-5.2-codex
- gpt-5-mini
# Optional OpenAI policy overlay.
# true (default): allow any model present in cached OpenAI /models.
# false: also require membership in model_allowlist.
allow_any_model: true
model_allowlist: []
gateway:
routes:
# Built-in OpenRouter route (Responses API). Set OPENROUTER_API_KEY in env to activate.
openrouter:
protocol: openai_responses
provider: openrouter
base_url: https://openrouter.ai/api/v1
api_key_env: OPENROUTER_API_KEY
# Route-first picker defaults for this route.
model_suggestions:
- anthropic/claude-opus-4-6
- google/gemini-3-pro-preview
- google/gemini-3-flash-preview
- moonshotai/kimi-k2.5
model_allowlist: []
allow_any_model: true
supports_background: false
supports_image_url: true
response_include:
- reasoning.encrypted_content
# Optional route-scoped retry overrides.
# retry_max_retries: null
# retry_max_total_attempts: null
# retry_deadline_seconds: null
# retry_attempt_timeout_seconds: null
# Built-in local Ollama route (OpenAI-compatible Responses API).
ollama:
protocol: openai_responses
provider: ollama
base_url: http://localhost:11434/v1
api_key_env: null
# Route-first picker defaults for local models.
model_suggestions:
- gpt-oss:20b
- gpt-oss:120b
model_allowlist: []
allow_any_model: true
supports_background: false
supports_image_url: true
allow_inline_data_url: true
# Optional route-scoped retry overrides.
# retry_max_retries: null
# retry_max_total_attempts: null
# retry_deadline_seconds: null
# retry_attempt_timeout_seconds: null
retries:
provider:
max_retries: 10
max_total_attempts: 25
deadline_seconds: null
attempt_timeout_seconds: null
base_backoff_seconds: 0.5
max_backoff_seconds: 8.0
jitter_ratio: 0.25
retry_after_max_seconds: 60.0
mcp:
max_retries: 3
max_total_attempts: 25
deadline_seconds: null
attempt_timeout_seconds: null
base_backoff_seconds: 1.0
max_backoff_seconds: 8.0
jitter_ratio: 0.25
retry_after_max_seconds: null
store:
max_retries: 5
max_total_attempts: 25
deadline_seconds: null
attempt_timeout_seconds: null
base_backoff_seconds: 0.05
max_backoff_seconds: 1.0
jitter_ratio: 0.25
retry_after_max_seconds: null
run:
# Default per-run behavior for one-shot runs.
background: false
# Stream idle timeout (no stream events/model bytes; resets on any event). Server may still enforce its own limits.
timeout_seconds: 600.0
# Stream progress timeout (whitespace-only tool-arg deltas do not count; null disables).
progress_timeout_seconds: 60.0
# Max streamed tool-argument chars per tool call (sum of deltas; null disables).
tool_args_max_chars: 200000
live: false # false = quiet summary, true = stream live events
json_output: false # true = emit JSON envelope instead of text output
# Optional tracing defaults; can also be overridden via CLI --trace on|off|ID:GROUP:key=val,...
trace_enabled: true # master tracing switch
#trace_id: "my-trace-id"
#group_id: "my-group-id"
#trace_metadata:
# run_id: "demo-run-1"
#trace_include_sensitive_data: false
repl:
approvals:
mode: prompt # prompt | auto
transcript:
tool_output_max_lines: 60
shell_preview_max_chars: 80
tool_detail_max_lines: 24
tool_detail_max_chars: 240
mcp_args_preview_max_chars: 240
attachments_max_lines: 6
attachments_path_max_chars: 120
ui:
theme: dark # dark | light
color_depth: auto # auto | mono | ansi | default | truecolor
editing_mode: vi # emacs | vi
mouse: true
completion: full # off | commands | full
max_transcript_entries: 400
ux:
markdown: true
reasoning: summary
reasoning_summary_max_chars: 0
diffs: summary
stream: final # final | live
verbosity: normal # quiet | normal | debug
tools:
# Max serialized tool output length (chars) for FunctionTools + MCP bridge.
max_chars: 85000
file_search:
vector_store_ids: []
max_num_results: 5
include_search_results: true
#filters: {}
#ranking_options: {}
web_search:
search_context_size: high # low|medium|high
user_location:
type: approximate
country: US
#filters: {}
shell:
# Maximum wall-clock time per shell command (ms).
timeout_ms: 60000
# Maximum output length enforced by agenterm (also forwarded to the model as a hint).
max_chars: 85000
sandbox:
network: allow # allow | deny
# Working directory for commands (resolved under the workspace root). When omitted, the workspace root is used.
#working_dir: .
# Custom env vars merged with safe defaults (PATH, HOME, SHELL, etc.).
# Set env: null to use defaults only.
env:
UV_CACHE_DIR: .uv-cache
# Apply patch uses the workspace editor; no tunables.
apply_patch: {}
inspect:
max_operations: 8
max_concurrency: 4
plan: {}
agent_run:
bundle: openai
agent_run_report: {}
image_generation:
model: gpt-image-1.5
#background: auto # transparent|opaque|auto
input_fidelity: high # high|low
moderation: low # auto|low
#output_compression: 75
output_format: png # png|webp|jpeg
#partial_images: 0
quality: high # low|medium|high|auto
#size: auto # 1024x1024|1024x1536|1536x1024|auto
#input_image_mask: {}
# Function tools are declared here; the actual Python callables are
# registered in code (see core.function_tools).
function_tools: []
# Example:
# - name: get_weather
# Dangerous overrides (tool refs).
dangerous:
add: []
remove: []
# Tool bundles for selection. Bundles are referenced by name via
# `tools.default_bundles` and the REPL `/tools` command. Tool keys encode
# capability families:
# - hosted:openai:* (OpenAI hosted tools; background-compatible only on OpenAI plane;
# gateway models reject hosted tools; gateway background runs are no-tool)
# - hosted:mcp:* (OpenAI hosted MCP connectors; background-compatible only on OpenAI plane;
# gateway models reject hosted tools; gateway background runs are no-tool)
# - fn:* (built-in FunctionTools; local harness)
# - fn:user:* (user FunctionTools; local harness)
# - mcp:* (client MCP servers; local harness)
bundles:
agenterm:
bundles:
- inspect
- plan
- subagents
- edit
- shell
- integrations
- extensions
inspect:
tools:
- fn:inspect
plan:
tools:
- fn:plan
subagents:
tools:
- fn:agent_run
- fn:agent_run_report
- fn:steward
edit:
tools:
- fn:apply_patch
shell:
tools:
- fn:shell
integrations:
selectors:
- mcp:*
- hosted:mcp:*
extensions:
selectors:
- fn:user:*
openai:
tools:
- hosted:openai:web_search
- hosted:openai:file_search
- hosted:openai:image_generation
scope: delegate
# Bundles that are active by default at startup (main scope).
default_bundles:
- agenterm
mcp:
# Declare MCP servers (client-managed) and connectors (provider-hosted) here.
connectors: []
servers: []
convert_schemas_to_strict: true
bridge:
# Hard caps for MCP tool outputs stored in history (size clamp via tools.max_chars).
max_content_items: 50
expose:
enabled: false
transport: stdio
host: 127.0.0.1
port: 8000
allow_dangerous: false
bundles: null
tools: null
# Example (stdio):
# servers:
# - key: files
# kind: stdio
# stdio:
# command: uvx
# args: ["mcp-files-server"]
# cwd: .
steward:
agent:
# Steward agent name (bundled/local/global agent file).
name: steward
# Optional model override for Steward tasks.
model: null
# Truncation mode for Steward tasks.
truncation: auto
# Optional output-token cap for Steward tasks.
max_output_tokens: 128000
# Inline instructions (mutually exclusive with path/source).
instructions: null
# Path to a Steward agent file (mutually exclusive with instructions/source).
path: null
# Optional agent file name to resolve (mutually exclusive with instructions/path).
source: null
tasks:
# Max queued Steward tasks per session/branch.
max_pending: 1
# Auto-cancel stale running Steward tasks before queue-limit checks.
# Set null to disable.
running_stale_seconds: 900
compression:
# snapshot | compaction_if_supported | both_if_supported
strategy: snapshot
# ask | auto
trigger: auto
# Percent of context_window (0 < x <= 1) that triggers compression.
threshold_percent: 0.5
# When running both snapshot + compaction, which continuation branch becomes active.
primary_branch: snapshot
# deny | ask | allow
drop_policy: deny
attachments:
# file_id_or_url_only | allow_inline_data_url
image_input_mode: file_id_or_url_only
# Allow inline data URLs when supported by the provider.
allow_inline_data_url: false
# Hard cap for inline payload bytes when enabled.
max_inline_bytes: 0
guardrails:
load_modules: []
# Names must correspond to guardrails registered in `core.guardrails_registry`.
# See `examples/guardrails/no_pii_input.py` for a reference input guardrail.
input: []
output: []
Run agenterm config save --scope global to generate the global baseline ~/.agenterm/config.yaml from the schema-derived template.
When you want project-specific overrides, run agenterm config save --scope local to seed .agenterm/config.yaml (from the global config when present), then adjust only the fields you care about for that project.
agenterm’s tool selection is structural: you select tool keys (bundles + direct keys), and the engine attaches exactly the resolved selection (config is not rewritten per-session).
Tool keys are capability identifiers (not adapters). They encode family:
fn:<name> — built‑in FunctionTools (fn:user:<name> for user‑defined).hosted:openai:<tool> — OpenAI hosted tools.hosted:mcp:<connector> — OpenAI‑hosted MCP connectors.mcp:<server_key> — client‑managed MCP servers (each server exposes many tools).Hosted tools (including hosted MCP connectors) are OpenAI‑plane only. Gateway
models use Chat Completions semantics and accept FunctionTools only, so
selecting hosted tools with gateway/... models is invalid and will fail at
runtime. MCP servers remain available on both planes via the MCP‑as‑FunctionTools
bridge. Background runs attach only hosted:* tools, so gateway background
runs execute without tool attachments.
Common keys:
hosted:openai:file_searchhosted:openai:web_searchhosted:openai:image_generationfn:inspectfn:shell (sandboxed on macOS + Linux)fn:apply_patchfn:planfn:agent_run_reportfn:stewardfn:agent_runtools.function_tools):
fn:user:<name>mcp.servers):
mcp:<server_key>mcp.connectors, provider-hosted):
hosted:mcp:<name>mcp.connectors) are provider-hosted and attach as the single tool named hosted_mcp (Agents HostedMCPTool). Select them via hosted:mcp:<name>.mcp.servers) are client-managed; their tools are discovered at runtime and exposed as function tools whose names begin with mcp__... (agenterm rewrites names to be globally unique and OpenAI-valid). Select servers via mcp:<server_key>.
tools.bundles: bundle name → bundle definition (bundles, tools, selectors, scope).tools.default_bundles: the default main-scope selection for the CLI and REPL.agenterm (composes all main-scope bundles: inspect, plan,
subagents, edit, shell, integrations, extensions).subagents bundle: sub-agent tools (agent_run, agent_run_report, steward).openai (OpenAI hosted tools for agent_run sub-agents).fn:agent_run uses tools.agent_run.bundle (default openai) for delegated
one-shot runs; delegate bundles are hosted-only and not selectable by the main
agent.--no-tools (CLI) and /tools off (REPL) hide all tools from the model without changing the selection. When the gate is off, agenterm strips tool config and MCP tools from the runtime agent.
shell and apply_patch operations always register approvals./approvals list / /approvals show <ID>).y/yes in the approvals modal input to approve the next pending item.n/no with optional trailing text (n <reason...>) to reject and supply a reason (forwarded to the model).y/n when no approvals remain pending./last approvals prints a bounded approvals audit trail (pending + resolved) for the active REPL session./approvals auto enables auto‑approval and approves everything currently pending./approvals prompt returns to manual approvals.agenterm run never prompts.tools.dangerous overrides) require
--allow-dangerous; without it, runs drop them from selection.Some tools require additional provider configuration to be truly available:
FileSearchTool only when vector_store_ids is non‑empty.file_search to avoid invalid requests.WebSearchTool when selected.cwd is workspace-relative (or omitted for workspace root); absolute cwd values are rejected.apply_patch:
~-prefixed paths at validation time.create_file with if_exists:error fails as conflict with reason=already_exists when the target already exists.delete_path on a missing path is a deterministic no-op success.ok:true; per-operation outcomes are in responses[] with status (ok|error|skipped) and typed error objects for failures.conflict, invalid_input, policy_denied, internal_error (with detailed error.details.reason).ok:false typed errors.plan:
get, set, add, update, delete, advance, reset) with stable step_ids.placement uses one object shape (mode, anchor_step_id|null); append/prepend require anchor_step_id=null, before/after require non-null anchor_step_id.patch uses one object shape (kind, step|null, status|null); kind determines which fields must be non-null.advance is an atomic “complete current + start next” transition.step_id and step text fields must include at least one non-whitespace character.plan_state, steps[{step_id, step, status}], explanation, revision, plan_created_at, plan_updated_at.field/reason details and may include guidance (for example, to call get for valid step ids).inspect:
search_text, find_paths, read_file,
read_bytes, list_tree, path_stats, runtime_info.request_id as string|null; the value is echoed in each response row.responses[index] matches requests[index])
and each response carries op, status, truncated, and optional error.ok and summary
(requested, ok, error, skipped).agent_run_report:
report_id.mode="summary".mode="full" returns a sanitized full payload (strips encrypted reasoning
tokens and provider-specific provider_data).mode="forensic" returns the raw persisted payload.agent_run:
op:"run" executes a single‑run delegated agent (max_turns=cfg.agent.max_turns) with model, instructions, and input.op:"discover_models" returns the dynamic delegated-model catalog for the current provider config (no provider run).report_id; the full report is stored in the artifacts vault.instructions, specify
objective, strict scope boundaries, required output format, stop condition,
and tool-use limits./artifacts agent-run <ID> or agenterm artifacts agent-run <ID>./status and /tools reflect both:
file_search without vector store IDs).The Responses API supports an include parameter to request additional sections of the response (tool results, images, reasoning, and so on). Agenterm CLI resolves include policy from one model contract path:
openai/<model> uses the default include set:
file_search_call.resultsweb_search_call.resultsweb_search_call.action.sourcesreasoning.encrypted_contentgateway/<route>/<model> with protocol: openai_responses:
providers.gateway.routes.<route>.response_include when set,["reasoning.encrypted_content"] as the default include set.gateway/<route>/<model> with protocol: litellm_chat_completions does not send response_include.There is no run-time include knob in CLI/REPL commands; include policy is centralized in route/model contract resolution.
Agenterm applies one adaptive optional-parameter retry across all run surfaces
(run, REPL, background submissions, Steward snapshot runs, and delegated
agent_run) when a provider returns a typed invalid-parameter error for an
optional model field. Current adaptive coverage:
include, including
reasoning.encrypted_content / logprobs include coupling)prompt_cache_retentiontop_logprobsverbosityreasoning (reasoning, reasoning.effort, reasoning.summary)store / metadataWhen adaptation occurs in delegated agent_run, warnings are recorded in the
persisted report payload.
Unsupported optional fields are cached per target model for subsequent calls in the same process.
MCP servers are configured under mcp.servers in config.yaml.
MCP servers are activated by selection: include mcp:<server_key> in a bundle's tools (or use selectors like mcp:* in the integrations bundle) and ensure that bundle is selected (typically via tools.default_bundles or the REPL /tools command).
MCP tools are exposed to the model as function tools with deterministic names:
mcp__<server_key>__<tool_name> (when OpenAI-valid and within 64 chars).For gateway models, MCP servers are converted into FunctionTools at run time; outputs are normalized into the standard agenterm tool output envelope (see ARCH.md, Tool I/O Contract) and surfaced like other FunctionTool results.
Construction is pure (config → server objects): engine.mcp_factory.build_mcp_servers.
Lifecycle is engine-owned (connect-before-use, cleanup-on-exit): engine.mcp_pool.McpServerPool.
Example (stdio):
mcp:
servers:
- key: files
kind: stdio
name: filesystem
tool_filter:
allowed_tool_names: ["read", "list"]
stdio:
command: uvx
args: ["mcp-files-server"]
cwd: .
Diagnostics commands:
uv run agenterm mcp servers — list configured MCP servers.uv run agenterm mcp status — show connection status and tool counts (agenterm mcp status --format json emits a single JSON envelope).uv run agenterm mcp tools — list all discovered MCP tools grouped by server.uv run agenterm mcp validate — connect and validate configuration.uv run agenterm mcp inspect — inspect tools exposed by the servers (prints names; --out PATH writes a JSON file).uv run agenterm mcp serve — run FastMCP to expose local FunctionTools (uses mcp.expose config).From inside the REPL:
/mcp refresh — triggers MCP tool discovery using the current selection./mcp status — shows MCP server status and discovered tool counts./tools and /status summaries accordingly.
/status include an explicit error marker; use /mcp status for per-server error detail and /mcp refresh to retry.Guardrails are configured via:
guardrails.load_modules: list[str] (optional)guardrails.input: list[str]guardrails.output: list[str]Guardrail names are resolved via core.guardrails_registry, which maps names to concrete input/output guardrail implementations.
agenterm ships with one built-in input guardrail:
no_secrets_input — blocks obvious credential-like strings (API keys, private keys) in user input.To enable it:
guardrails:
input:
- no_secrets_input
For custom guardrails, list modules to import (so their register_*_guardrail(...) calls run at import time), then reference their registered names:
guardrails:
load_modules:
- my_project.guardrails
input:
- my_guardrail_name
The examples directory includes a reference guardrail:
examples/guardrails/no_pii_input.py — a simple “no PII in input” guardrail.Execution behavior:
For local development in this repo:
Install dependencies:
uv sync
Basic smoke tests:
uv run python -m compileall src
uv run agenterm run "describe this repo"
uv run agenterm repl
Run the gate from the repo root:
uv run devtools/gate.py # default gate (offline; no secrets; no network)
uv run devtools/gate.py --full # include provider/network integration tests (requires credentials)
uv run devtools/gate.py --no-tests # skip pytest entirely (fast feedback)
What it runs (in order):
ruff check --fix src devtools (lint rules configured in pyproject.toml)ruff format src devtools (applies formatting fixes)basedpyright . (scoped to src/devtools via pyproject.toml include; excludes .uv-cache/.worktrees)python -m compileall src devtoolspytest -q (omitted with --no-tests; exit code 5 for “no tests collected” is treated as success)pytest -q -m integration_provider (only with --full; opt-in tests that hit real providers/network and require credentials)agenterm --help smokeexcept:, no reflection, no silent swallows, no eval/exec, no shell=True, no empty defs, no Any/cast, no broad object annotationspython -m devtools.policy_dict_params (policy: forbid dict[...] in function parameter annotations; use Mapping/MutableMapping)python -m devtools.file_size_check (≤500 lines / 18 kB per file under src/devtools)uv lock --check~/.agenterm/.envagenterm relies on OpenAI environment variables plus any gateway route key env vars you configure.
Environment loading:
~/.agenterm/.env.
.env files from your project directory to reduce the risk of accidentally committing secrets.override=False)..env.example as a template; copy it to ~/.agenterm/.env if you want a file-based setup.OPENAI_API_KEY as an environment variable via your secrets manager (do not rely on the global file).OPENAI_API_KEY (required for openai/... models):
agenterm run and agenterm inspect response fail fast with a clear message when an OpenAI model is selected and no key is configured./config key <OPENAI_API_KEY> to save it to ~/.agenterm/.env (and set it for the current session).Gateway route keys (optional):
providers.gateway.routes.*.api_key_env.OPENROUTER_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, XAI_API_KEY.gateway/ollama/* uses api_key_env: null (no key required for
default localhost setup).OPENAI_ORG_ID — maps to the OpenAI client organization.OPENAI_PROJECT_ID — maps to the OpenAI client project.OPENAI_BASE_URL — overrides the API base URL (for example, Azure or another OpenAI‑compatible endpoint).
providers.openai.base_url is set, it overrides this value.OPENAI_WEBHOOK_SECRET — webhook verification secret; exposed for completeness, though Agenterm CLI does not currently expose webhook endpoints.Availability:
SeatbeltBackend (sandbox-exec).LinuxBackend (bwrap / bubblewrap).fn:shell.The shell tool runs commands in an OS-level sandbox backend with stable guarantees:
agenterm launched)/tmp, /var/tmp, plus macOS temp roots)tools.shell.sandbox.network (allow | deny)PATH, HOME, SHELL, etc.) with optional custom vars via tools.shell.envConfiguration:
tools:
shell:
sandbox:
network: allow # "allow" | "deny"
Full shell features work within the sandbox (pipes, redirection, chaining). Writes outside the workspace are blocked at OS level regardless of command structure.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.6.0 | 27 Feb 2026 | 8 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:c0cf23cf2eb884504794e749bd057ff797c26574f7fb6cfc107c635a8b1328b0