Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
58 changes: 58 additions & 0 deletions docs/guides/getting-started/choosing-a-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
sidebar_label: Choose a Runtime
---

# Choose an agent 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 | Description | When to use |
|---------|-------------|-------------|
| `claude` | Claude Code (production default) | Most deployments — mature, full sub-agent support |
| `pi` | [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 alternative; no sub-agent tool yet, so `review`/`retro` run single-context; see [Runtimes](../../runtimes.md) for known constraints |

## How to select a runtime

### At setup time

`fullsend github setup <owner/repo>` asks which runtime to use when run from a terminal (press Enter for `claude`), and the setup PR it opens describes the choice. To set it explicitly, pass `--runtime`:

```bash
fullsend github setup <owner/repo> \
--inference-wif-provider "<wif-url>" \
--runtime pi
```

### In config

Set `runtime:` in the repo's `.fullsend/config.yaml`:

```yaml
runtime: pi
```

For fleets managed through `repos.yaml`, set `defaults.runtime` (or a per-entry `runtime`) and run `fullsend repos install`, or pass `fullsend repos install --runtime pi` for repos the command adds:

```bash
fullsend repos set-default defaults.runtime pi
```

To try a runtime or model on one run without changing the repo, use the per-run overrides — `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).

No workflow file change is needed — the runner reads the config at the start of every run.

## 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.

The `--runtime` flag selects which agent runtime to use (e.g. `claude` or `pi`); 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