fullsend run
Execute an agent locally in a sandbox. fullsend run resolves the agent harness, provisions a sandbox container, and runs the agent to completion.
Usage
fullsend run <agent-name> [flags]Flags
| Flag | Description |
|---|---|
--fullsend-dir | Path to the .fullsend configuration directory |
--runtime | Override the agent runtime from config.yaml for this run (claude, pi, codex, dummy or dummy-playback); also FULLSEND_RUNTIME |
--model | Override the harness/agent model for this run (alias, model id, or provider/id on pi and codex — codex takes OpenAI ids only); also FULLSEND_MODEL |
--effort | Override the harness effort level for this run (low…max); also FULLSEND_EFFORT |
--output-dir | Base directory for run output (default: /tmp/fullsend) |
--target-repo | Path to the target repository |
--fullsend-binary | Path to a Linux fullsend binary to copy into the sandbox |
--env-file | Load environment variables from a dotenv file (repeatable) |
--no-post-script | Skip post-script execution |
--keep-sandbox | Skip sandbox deletion after the run |
--debug [filter] | Enable agent runtime debug logging with optional category filter (e.g. "api,hooks") |
--forge | Forge platform to use (e.g. "github", "gitlab"); auto-detected from CI env vars when omitted |
--offline | Reject network fetches; only use cached remote resources |
--max-depth | Maximum dependency depth for transitive resolution (0 disables) |
Plan block
At startup, fullsend run prints a plan block summarizing the resolved configuration:
Agent: code
Role: code
Model: sonnet
Effort: high
Runtime: claude (from /path/to/.fullsend/config.yaml)
Image: fullsend-sandbox:latestThe Runtime line shows which runtime was selected and the config source it was read from. When no config.yaml exists, the source reads default (config not found).
Runtime selection
The runtime for a run is resolved once, in this order: --runtime flag, FULLSEND_RUNTIME, runtime: on the agent's agents: entry in config.yaml / .fullsend/config.yaml, the repo-wide runtime: there, then the built-in claude. The same order applies to the model (--model, FULLSEND_MODEL, model: on the agent's agents: entry, harness model:, agent frontmatter; FULLSEND_PI_MODEL on pi and FULLSEND_CODEX_MODEL on codex are lower-precedence aliases, each read only when that runtime is the one selected) and to effort (--effort, FULLSEND_EFFORT, effort: on the agent's agents: entry, harness effort:). <agent> is the name given to fullsend run (triage, code, …); see Runtimes — per-agent settings. FULLSEND_FALLBACK_MODELS=a,b becomes Claude Code's --fallback-model; pi and codex ignore it with a warning.
The plan block prints Runtime: <name> (from <source>) and, when an override applied, Model: <value> (from <source>); stderr carries runtime: selected "<name>" from <source> (and model: requested "<value>" from <source>) for scripts. A value from the config file is labelled with the file path, suffixed agents.<name> when the agent's entry decided. An invalid override (unknown runtime, unknown effort level, an agents: entry that names no agent) fails before the sandbox is created.
# try a repo's triage on pi with Gemini Flash, without touching its config
fullsend run triage --fullsend-dir . --target-repo ../repo \
--runtime pi --model google-vertex/gemini-2.5-flash --effort mediumOutput artifacts
Each run produces artifacts in the output directory:
| File | Description |
|---|---|
metrics.json | Behavioral metrics: tokens, cost, model, runtime, iterations |
transcripts/ | Agent conversation transcripts |
claude-debug.log, pi-debug.log or codex-debug.log | Debug log (when --debug is set) |
metrics.json fields
| Field | Description |
|---|---|
runtime | Runtime that executed the run (e.g. claude, pi, codex) |
model | Model the provider reported using |
requested_runtime | Runtime selected for the run (config file, or a --runtime/FULLSEND_RUNTIME override) |
requested_model | Model the harness/agent requested |
override_source | Where requested_model came from (--model flag, FULLSEND_MODEL, FULLSEND_PI_MODEL, FULLSEND_CODEX_MODEL, <config path> agents.<name>, harness, default) |
runtime_source | Where requested_runtime came from (--runtime flag, FULLSEND_RUNTIME, the config file path — suffixed agents.<name> when the agent's entry decided — or default (config not found)) |
total_cost_usd | Total inference cost in USD, as reported by the runtime (raw floating-point aggregate across all iterations; no fullsend-side pricing-table fallback). See Cost data contract |
num_turns | Number of conversation turns |
iterations | Number of retry iterations |
OpenAI credentials on pi and codex
A fullsend-openai provider (providers: [openai] on the harness, openai/<id> models on pi or codex) gets its credential from the runner, never from the harness or the sandbox:
| Runner environment | Effect |
|---|---|
FULLSEND_OPENAI_AUDIENCE, FULLSEND_OPENAI_IDENTITY_PROVIDER_ID, FULLSEND_OPENAI_SERVICE_ACCOUNT_ID | Workload Identity Federation (GitHub Actions only): the run exchanges the job's OIDC token for a short-lived OpenAI token, refreshes it before expiry, and refuses a token whose mapping grants more than model access. All three must be set together; when unset, the inference.openai block of config.yaml (written by fullsend github setup --openai-*) supplies them — except on a machine without a GitHub OIDC endpoint where OPENAI_API_KEY is set, which then wins. |
OPENAI_API_KEY | Static key for local runs (used only when the three above are unset). In harness YAML, env.sandbox and provider definitions ${OPENAI_API_KEY} expands to the empty string (like the other runner-only variables), and it is never passed to pre/post scripts; the sandbox sees only the gateway placeholder. |
In CI the run prepares .fullsend/providers/ from the upstream defaults, so a file there with a scaffold-shipped name (openai.yaml, github-ro.yaml, vertex-ai.yaml, …) is replaced by the upstream copy; give repository-specific providers their own file name. A harness that declares the bare name openai with no providers/openai.yaml on disk gets the definition built into fullsend; other bare names still need a file.
Both paths create a provider named after the run and remove it when the run ends. Setup and troubleshooting: OpenAI Workload Identity.
Related
- Running Agents Locally for a step-by-step walkthrough
- Runtimes for runtime selection and capabilities
- CLI internals for the full command tree
