Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/reusable-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,9 @@ jobs:
TRIAGE_TARGET_REPO_DIR: target-repo
TRIAGE_ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
TRIAGE_CLOUD_ML_REGION: ${{ inputs.gcp_region }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, TRIAGE_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Run triage agent
Expand Down Expand Up @@ -755,6 +758,9 @@ jobs:
CODE_ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
CODE_CLOUD_ML_REGION: ${{ inputs.gcp_region }}
CODE_ISSUE_NUMBER: ${{ fromJSON(needs.route.outputs.event_payload).issue.number }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, CODE_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Run code agent
Expand Down Expand Up @@ -877,6 +883,9 @@ jobs:
REVIEW_TARGET_REPO_DIR: target-repo
REVIEW_ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
REVIEW_CLOUD_ML_REGION: ${{ inputs.gcp_region }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, REVIEW_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Run review agent
Expand Down Expand Up @@ -1143,6 +1152,9 @@ jobs:
FIX_HUMAN_INSTRUCTION: ${{ steps.context.outputs.instruction }}
FIX_FIX_ITERATION: ${{ steps.context.outputs.iteration }}
FIX_REPO_FULL_NAME: ${{ github.repository }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, FIX_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Run fix agent
Expand Down Expand Up @@ -1246,6 +1258,9 @@ jobs:
RETRO_TARGET_REPO_DIR: target-repo
RETRO_ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
RETRO_CLOUD_ML_REGION: ${{ inputs.gcp_region }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, RETRO_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Run retro agent
Expand Down Expand Up @@ -1329,6 +1344,9 @@ jobs:
PRIORITIZE_PROJECT_NUMBER: ${{ inputs.project_number }}
PRIORITIZE_ANTHROPIC_VERTEX_PROJECT_ID: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
PRIORITIZE_CLOUD_ML_REGION: ${{ inputs.gcp_region }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, PRIORITIZE_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: bash .github/scripts/setup-agent-env.sh

- name: Create empty target-repo directory
Expand Down Expand Up @@ -1620,6 +1638,9 @@ jobs:
MATRIX_ROLE: ${{ matrix.role }}
GCP_PROJECT: ${{ secrets.FULLSEND_GCP_PROJECT_ID }}
GCP_REGION: ${{ inputs.gcp_region }}
# Per-run runtime/model/effort overrides from repository variables
# (FULLSEND_MODEL, <ROLE>_FULLSEND_MODEL, ...); see docs/runtimes.md.
FULLSEND_REPO_VARS: ${{ toJSON(vars) }}
run: |
set -euo pipefail
ROLE_UPPER=$(echo "${MATRIX_ROLE}" | tr '[:lower:]' '[:upper:]')
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ script-test:
$(call run-timed,bash .github/scripts/check-fix-eligibility-test.sh)
$(call run-timed,bash internal/scaffold/fullsend-repo/scripts/reconcile-repos-test.sh)
$(call run-timed,bash internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review-test.sh)
$(call run-timed,bash internal/scaffold/fullsend-repo/.github/scripts/setup-agent-env-test.sh)
$(call run-timed,bash hack/gitlab-runner-vm/executor/prepare_validation_test.sh)
$(call run-timed,python3 skills/topissues/scripts/topissues_test.py)
$(call run-timed,python3 skills/nextwork/scripts/nextwork_test.py)
Expand Down
7 changes: 6 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export default defineConfig({
{ text: "fullsend inference", link: "/cli/inference" },
{ text: "fullsend mint", link: "/cli/mint" },
{ text: "fullsend repos", link: "/cli/repos" },
{ text: "fullsend run", link: "/cli/run" },
],
},
],
Expand All @@ -195,12 +196,17 @@ export default defineConfig({
link: "/guides/getting-started/",
items: [
{ text: "Getting Inference", link: "/guides/getting-started/getting-inference" },
{ text: "Choose a Runtime", link: "/guides/getting-started/choosing-a-runtime" },
{ text: "Configuring GitHub", link: "/guides/getting-started/configuring-github" },
{ text: "Per-Org Mode", link: "/guides/getting-started/org-mode" },
{ text: "Repo Management", link: "/guides/getting-started/repo-management" },
{ text: "Operations", link: "/guides/getting-started/operations" },
],
},
{
text: "Runtimes",
link: "/runtimes",
},
{
text: "Agents",
collapsed: true,
Expand Down Expand Up @@ -244,7 +250,6 @@ export default defineConfig({
items: [
{ text: "Vision", link: "/vision" },
{ text: "Architecture", link: "/architecture" },
{ text: "Runtimes", link: "/runtimes" },
{ text: "Glossary", link: "/glossary" },
],
},
Expand Down
2 changes: 1 addition & 1 deletion docs/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Download the latest binary from [GitHub Releases](https://github.com/fullsend-ai

| Command | Description |
|---------|-------------|
| `fullsend run` | Execute an agent locally in a sandbox. See [running agents locally](../guides/user/running-agents-locally.md). |
| [`fullsend run`](run.md) | Execute an agent locally in a sandbox. See [running agents locally](../guides/user/running-agents-locally.md). |
| `fullsend lock [agent-name]` | Pin remote dependencies to `lock.yaml` |
| `fullsend scan` | Run security scanners on agent input/output |
| `fullsend eval-measure` | Score wild-run traces into `eval-measurements.jsonl`. See [Eval measurements](../guides/infrastructure/eval-measurements.md). |
Expand Down
4 changes: 3 additions & 1 deletion docs/cli/repos.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ required in this case. This enables a greenfield setup without running

Runs in three phases:

1. **Manifest add** — repos specified as positional arguments that are not already in the manifest are added (`--forge` is required when the target platform cannot be inferred). Per-repo overrides (`--inference-region`, `--fullsend-ref`, `--mint-url`, `--allowed-remote-resources`) are written to the manifest entry.
1. **Manifest add** — repos specified as positional arguments that are not already in the manifest are added (`--forge` is required when the target platform cannot be inferred). Per-repo overrides (`--inference-region`, `--fullsend-ref`, `--mint-url`, `--allowed-remote-resources`, `--runtime`) are written to the manifest entry.
2. **Provision** — repos in the manifest that are not yet provisioned are installed (scaffold files, variables, secrets). Repos with a guard variable set but other components missing are repaired automatically.
3. **Convergence** — repos that are already installed are checked for component drift (workflow, thin callers, variables, secrets — repaired automatically) and scaffold ref drift (upgraded automatically).

Expand Down Expand Up @@ -118,6 +118,7 @@ When repos are specified as positional arguments, only those repos are processed
| `--fullsend-ref` | | Per-repo fullsend workflow ref override |
| `--mint-url` | | Per-repo mint URL override |
| `--allowed-remote-resources` | | Per-repo allowed remote resources override |
| `--runtime` | | Agent runtime (`claude`, `pi`) recorded for repos this command adds; existing entries keep their `runtime` / `defaults.runtime` |
| `--gitlab-bot-token` | | GitLab bot PAT for free-tier instances that don't support project access tokens (env: `FULLSEND_GITLAB_BOT_TOKEN`) |

### GitLab bot token
Expand Down Expand Up @@ -255,6 +256,7 @@ fullsend repos set-default github.mint_url "" # removes the key
| Key | Type | Description |
|-----|------|-------------|
| `defaults.allowed_remote_resources` | comma-separated URLs | HTTPS URLs agents may fetch at runtime |
| `defaults.runtime` | `claude` or `pi` | Agent runtime written as each repo's `runtime:` at install; a per-entry `runtime` overrides it (`none` stops the chain) |
| `github.url` | URL | GitHub instance URL (default: `https://github.com`) |
| `github.mint_url` | URL | Token mint service URL (defaults to `https://mint.fullsend.sh` in public mode) |
| `github.mint_mode` | `public` or `private` | Controls the default mint URL: `public` defaults to `https://mint.fullsend.sh`; `private` requires an explicit `mint_url` (default: `public`) |
Expand Down
89 changes: 89 additions & 0 deletions docs/cli/run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
sidebar_label: fullsend run
---

# 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

| Flag | Description |
|------|-------------|
| `--fullsend-dir` | Path to the `.fullsend` configuration directory |
| `--runtime` | Override the agent runtime from `config.yaml` for this run (`claude`, `pi`, `dummy`); also `FULLSEND_RUNTIME` |
| `--model` | Override the harness/agent model for this run (alias, model id, or `provider/id` on pi); 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: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`, the per-repo `runtime:` in `config.yaml` / `.fullsend/config.yaml`, then the built-in `claude`. The same order applies to the model (`--model`, `FULLSEND_MODEL`, harness `model:`, agent frontmatter; `FULLSEND_PI_MODEL` is a lower-precedence alias on pi) and to effort (`--effort`, `FULLSEND_EFFORT`, harness `effort:`). `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. An invalid override (unknown runtime, unknown effort level) 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:

| File | Description |
|------|-------------|
| `metrics.json` | Behavioral metrics: tokens, cost, model, runtime, iterations |
| `transcripts/` | Agent conversation transcripts |
| `claude-debug.log` or `pi-debug.log` | Debug log (when `--debug` is set) |

### metrics.json fields

| Field | Description |
|-------|-------------|
| `runtime` | Runtime that executed the run (e.g. `claude`, `pi`) |
| `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`, `harness`, `default`) |
| `runtime_source` | Where `requested_runtime` came from (`--runtime flag`, `FULLSEND_RUNTIME`, the config file path, or `default (config not found)`) |
| `total_cost_usd` | Total inference cost |
| `num_turns` | Number of conversation turns |
| `iterations` | Number of retry iterations |

## Related

- [Running Agents Locally](../guides/user/running-agents-locally.md) for a step-by-step walkthrough
- [Runtimes](../runtimes.md) for runtime selection and capabilities
- [CLI internals](../guides/dev/cli-internals.md) for the full command tree
2 changes: 1 addition & 1 deletion docs/contributing/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The `admin` command group's `install`/`uninstall`/`analyze`/`enable`/`disable` s

| Category | Files |
|----------|-------|
| CLI reference | _(no dedicated page)_ |
| CLI reference | `docs/cli/run.md` |
| Guides | `docs/guides/user/running-agents-locally.md`, `docs/guides/user/building-custom-agents.md`, `docs/guides/dev/cli-internals.md` |
| ADRs | `docs/ADRs/0036-agent-execution-sandbox.md` |
| Contributing | `docs/contributing/sandbox-topology.md` |
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ This section contains easy and to the point guides to help you
set up Fullsend. These are intended to be read in a certain order:

1. [Getting Inference](getting-inference.md)
2. [Configuring GitHub](configuring-github.md)
3. [Organization Mode](org-mode.md)
2. [Choose an agent runtime](choosing-a-runtime.md)
3. [Configuring GitHub](configuring-github.md)
4. [Organization Mode](org-mode.md)
38 changes: 38 additions & 0 deletions docs/guides/getting-started/choosing-a-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
sidebar_label: Choose a Runtime
---

# Choose an agent runtime

> **Claude Code is the stable default.** The fleet agents have run on Claude Code in production for a long time; it is what a new installation gets unless you ask for something else. **pi is in its enablement (experimental) phase** — it works end to end for `triage`, `prioritize`, `code` and `fix`, has no sub-agent tool yet (`review`/`retro` run in a single context), and its fleet pilot is still in progress. Unless you are taking part in that pilot, keep the default.

This page explains what the choice means and where it is made. **You do not select anything on this page** — the selection happens in the next step, [Configuring GitHub](configuring-github.md), when `fullsend github setup` prompts for the runtime (press Enter for `claude`) or when you pass `--runtime`.

Fullsend supports multiple agent runtimes. A runtime is the program that runs inside the sandbox and drives the model — it owns the tool-use loop, hook wiring, and transcript format. The runner (fullsend) owns everything outside: sandbox lifecycle, credentials, metrics, and the verdict.

## Available runtimes

| Runtime | Status | Description | When to use |
|---------|--------|-------------|-------------|
| `claude` | **Stable (default)** | Claude Code on Vertex AI | Every production deployment — mature, full sub-agent support for `review`/`retro` |
| `pi` | Experimental (enablement phase) | [Pi](https://github.com/earendil-works/pi) — Claude on Vertex by default; any provider pi supports by model name (e.g. Gemini on Vertex with the same credentials) | Opt-in pilots only; no sub-agent tool yet, so `review`/`retro` run single-context; see [Runtimes](../../runtimes.md) for known constraints |

## When and how the runtime is selected

1. **Next step — Configuring GitHub.** `fullsend github setup <owner/repo>` asks which runtime to use when run from a terminal; press Enter to keep `claude`. Passing `--runtime` skips the prompt. The setup PR it opens records the choice in `.fullsend/config.yaml` and describes how to change it. Nothing runs on this page — continue with [Configuring GitHub](configuring-github.md).
2. **Later — changing it.** Edit `runtime:` in the repo's `.fullsend/config.yaml` (the setup PR shows the key), or re-run `fullsend github setup <owner/repo> --runtime <claude|pi>`. Fleets managed through `repos.yaml` set `defaults.runtime` (or a per-entry `runtime`) — `fullsend repos set-default defaults.runtime pi` — and run `fullsend repos install`; see [fullsend repos](../../cli/repos.md).
3. **Per run — trying without changing the repo.** `fullsend run --runtime pi --model google-vertex/gemini-2.5-flash`, or the `FULLSEND_RUNTIME` / `FULLSEND_MODEL` / `FULLSEND_EFFORT` environment variables (flag beats environment beats config). In CI the same names work as repository variables. Reference: [fullsend run](../../cli/run.md) and [Runtimes — selecting and overriding](../../runtimes.md#selecting-and-overriding).

## Where to see what ran

After a run completes, the selected runtime and model appear in several places:

- **Run plan block** — `Runtime: <name> (from <source>)` printed at the start of every `fullsend run`
- **Status comment** — the terminal status comment on the issue/PR includes a footer with runtime, model, effort, and cost
- **metrics.json** — `runtime`, `requested_runtime`, `runtime_source`, `requested_model`, and `override_source` fields record what was selected and why
- **stderr** — `runtime: selected "<name>" from <source>` for script consumers

## Next steps

- [Configuring GitHub](configuring-github.md) to set up your repo
- [Runtimes](../../runtimes.md) for the full runtime reference, including model override precedence and the capability table
2 changes: 2 additions & 0 deletions docs/guides/getting-started/configuring-github.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ fetched content before committing.
> because the preset provides its own configuration. `--config` is only
> valid for per-repo mode.

This is where the agent runtime is selected: on a terminal, `fullsend github setup` asks once (press Enter to keep `claude`, the stable default); `--runtime` sets it explicitly. `pi` is experimental and meant for the enablement pilot — see [Choose a Runtime](choosing-a-runtime.md) for what the runtimes are and how to change the selection after setup.

## Testing Fullsend

After installing open a new issue or comment `/fs-triage` in an open issue. Then visit the
Expand Down
4 changes: 3 additions & 1 deletion docs/guides/user/running-agents-locally.md
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,9 @@ Stop reasons: toolUse=2, stop=1

| Variable | Description |
|----------|-------------|
| `FULLSEND_PI_MODEL` | Override the model id (runner env) |
| `FULLSEND_MODEL` (or `fullsend run --model`) | Override the model for the run on any runtime; `FULLSEND_PI_MODEL` is kept as a pi-only alias |
| `FULLSEND_RUNTIME` (or `--runtime`) | Override the runtime selected by `config.yaml` |
| `FULLSEND_EFFORT` (or `--effort`) | Override the harness effort level |
| `FULLSEND_PI_PROVIDER` | Override the inference provider (runner env) |
| `FULLSEND_PI_BASH_ALLOWLIST` | Set to `enforce` to make the Bash first-token allowlist block instead of warn |

Expand Down
Loading
Loading