Skip to content

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 ​

bash
fullsend run <agent-name> [flags]

Flags ​

FlagDescription
--fullsend-dirPath to the .fullsend configuration directory
--runtimeOverride the agent runtime from config.yaml for this run (claude, pi, dummy); also FULLSEND_RUNTIME
--modelOverride the harness/agent model for this run (alias, model id, or provider/id on pi); also FULLSEND_MODEL
--effortOverride the harness effort level for this run (low…max); also FULLSEND_EFFORT
--output-dirBase directory for run output (default: /tmp/fullsend)
--target-repoPath to the target repository
--fullsend-binaryPath to a Linux fullsend binary to copy into the sandbox
--env-fileLoad environment variables from a dotenv file (repeatable)
--no-post-scriptSkip post-script execution
--keep-sandboxSkip sandbox deletion after the run
--debug [filter]Enable agent runtime debug logging with optional category filter (e.g. "api,hooks")
--forgeForge platform to use (e.g. "github", "gitlab"); auto-detected from CI env vars when omitted
--offlineReject network fetches; only use cached remote resources
--max-depthMaximum 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:latest

The 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 is a lower-precedence alias on pi) 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 ignores 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.

bash
# 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 medium

Output artifacts ​

Each run produces artifacts in the output directory:

FileDescription
metrics.jsonBehavioral metrics: tokens, cost, model, runtime, iterations
transcripts/Agent conversation transcripts
claude-debug.log or pi-debug.logDebug log (when --debug is set)

metrics.json fields ​

FieldDescription
runtimeRuntime that executed the run (e.g. claude, pi)
modelModel the provider reported using
requested_runtimeRuntime selected for the run (config file, or a --runtime/FULLSEND_RUNTIME override)
requested_modelModel the harness/agent requested
override_sourceWhere requested_model came from (--model flag, FULLSEND_MODEL, FULLSEND_PI_MODEL, <config path> agents.<name>, harness, default)
runtime_sourceWhere 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_usdTotal 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_turnsNumber of conversation turns
iterationsNumber of retry iterations

OpenAI credentials on pi ​

A fullsend-openai provider (providers: [openai] on the harness, openai/<id> models on pi) gets its credential from the runner, never from the harness or the sandbox:

Runner environmentEffect
FULLSEND_OPENAI_AUDIENCE, FULLSEND_OPENAI_IDENTITY_PROVIDER_ID, FULLSEND_OPENAI_SERVICE_ACCOUNT_IDWorkload 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_KEYStatic 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.

Content