# Forge Repository Agents V1

Every Forge repository has its own durable, multi-turn agent. A repository
agent can read only that repository, and every run is pinned to the exact
source SHA recorded when Forge accepts the message. Reusing a thread continues
the conversation; it does not widen the agent to other repositories.

V1 ships Instant generally and keeps Workspace Alpha behind an explicit
repository/user allowlist:

- **Instant** runs inside the Forge API Worker. Before inference, Forge
  deterministically searches paths and reads a bounded evidence set from the
  exact accepted source SHA. This keeps the model call inside the Worker's
  execution window; agent-directed multi-round retrieval belongs to Workspace.
  Path discovery traverses the exact tree once per run, reads at most two
  parallel 10,000-character excerpts, and gives the whole execution a
  24-second deadline so an accepted run cannot outlive the Worker background
  window without a terminal failure record. Follow-up retrieval incorporates
  the immediately preceding grounded exchange, while the inference prompt
  retains only a bounded recent conversation window.
  Instant rejects sensitive paths, symlinks, binary or oversized files,
  validates every answer citation against the supplied evidence, and answers
  with Workers AI.
  It has no shell, test runner, network tools, secrets, repository writes,
  branch writes, or pull-request authority.
- **Workspace Alpha** runs pinned OpenCode 1.18.11 inside one run-scoped
  Cloudflare Sandbox materialized from the exact accepted Forge SHA. The
  sandbox receives only a short-lived model token for a narrow Forge-owned
  endpoint. It has no Forge PAT, GitHub installation token, provider master
  key, Cloudflare deployment credential, or output-ref authority. Forge
  independently inspects the stopped filesystem, rejects unsafe entries and
  `.git` mutation, runs server-declared tests in both the execution sandbox and
  a fresh trusted checkout, rebuilds the change from the accepted SHA, then
  publishes the fenced `agent/*` branch and one deduplicated draft Forge pull
  request. Forge is both the Git remote and pull-request host; Workspace does
  not require or contact GitHub.
  This profile is visible and runnable only for users with repository write
  permission plus `agent:write` who also match the server-owned Alpha
  allowlist. Everyone else continues to see the non-runnable adapter state.
- **Build** and **Machine** are reserved future profiles and are unavailable.

Instant can inspect and explain code but cannot claim to implement, execute,
test, or publish a change. Only the allowlisted Workspace Alpha path has that
authority.

## Conversation identity

Thread IDs are readable handles:

```text
agent_thread_0123456789abcdef0123456789abcdef
```

Omit `thread_id` when creating a thread and Forge assigns one. Supplying a valid
thread ID lets an integration choose a stable conversation handle. Every
message creates its own `agent_message_...` and `agent_run_...` records.

The repository-agent API does not use `Idempotency-Key`. A client that needs
retry correlation supplies `client_message_id` on a message. Reusing that ID
with the same normalized message, source, and execution request returns the
existing run; reusing it with different input returns `409 message_conflict`.

## API

All responses use `Cache-Control: private, no-store`.

```text
GET  /api/repos/:owner/:repo/agent/execution-profiles
POST /api/repos/:owner/:repo/agent/threads
GET  /api/repos/:owner/:repo/agent/threads
GET  /api/repos/:owner/:repo/agent/threads/:thread_id
POST /api/repos/:owner/:repo/agent/threads/:thread_id/messages
GET  /api/repos/:owner/:repo/agent/threads/:thread_id/events?after=:cursor
POST /api/repos/:owner/:repo/agent/threads/:thread_id/archive
```

Create a thread:

```bash
curl -X POST "$FORGE_URL/api/repos/OWNER/REPO/agent/threads" \
  -H "Authorization: Bearer $FORGE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{}'
```

Send an Auto message. Auto starts with the least-privileged useful profile,
which is Instant in V1:

```bash
curl -X POST "$FORGE_URL/api/repos/OWNER/REPO/agent/threads/$THREAD_ID/messages" \
  -H "Authorization: Bearer $FORGE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{
    "message":"Explain the authentication boundary.",
    "client_message_id":"slack-event-019f1234",
    "execution":{"mode":"auto","max_compute":"workspace"}
  }'
```

Use an explicit least-privilege ceiling when an integration never wants a
future escalation:

```json
{
  "message": "Which module owns token validation?",
  "execution": { "mode": "instant", "max_compute": "instant" }
}
```

The API returns `202` only after the user message, queued run, frozen source
SHA, queued event, and dispatch outbox row are committed together. The movable
repository UI polls the cursor event API and refreshes the authoritative thread
view until the run is terminal.

## Forge CLI

The headless `sf agent` commands use the same repository-agent API and durable
contracts as the repository UI. Inspect live tier availability before choosing
compute:

```bash
sf agent profiles OWNER/REPO --json
```

An omitted thread creates one and returns its durable handle. Keep that handle
to move down to an Instant answer or up to an allowlisted Workspace run without
forking the conversation:

```bash
sf agent message OWNER/REPO \
  --message "Explain the publication fence" \
  --mode instant \
  --client-message-id example-instant-001 \
  --json

sf agent message OWNER/REPO \
  --thread agent_thread_0123456789abcdef0123456789abcdef \
  --message "Implement the focused regression and run its test" \
  --mode workspace \
  --source-ref refs/heads/main \
  --client-message-id example-workspace-001 \
  --json
```

`sf agent view` returns the authoritative messages, runs, approvals, artifacts,
and receipts. `sf agent events` resumes normalized events after a cursor.
Cancellation and approval resolution require the exact repository/thread/run
identity and explicit confirmation. The CLI never accepts model endpoints,
provider credentials, output refs, or other authority that belongs to Forge.

## Stateless MCP compatibility

Forge also exposes the same authority through the official MCP TypeScript SDK:

```text
POST /mcp/agents
Authorization: Bearer <Forge PAT or agent service-principal key>
```

The Phase 1 server supports MCP 2026-07-28 and the SDK's stateless fallback for
older Streamable HTTP clients. It exposes four tools:

- `forge_agent_message` creates or continues a thread and accepts one Instant
  run. If `thread_id` is omitted, Forge assigns it.
- `forge_agent_get_thread` reads the authoritative messages and runs.
- `forge_agent_list_threads` lists recent threads for one repository.
- `forge_agent_list_events` reads durable events after a cursor.

MCP is an adapter, not a second agent runtime. The tools call the same
protocol-neutral service as REST, use the same repository grants, and return
the same `agent_thread_...`, `agent_run_...`, source SHA, receipt, and event
records. A repo-bound token cannot name another repository to widen authority.

The message tool returns after durable acceptance. Poll the thread or events
tool for completion. MCP Tasks, OAuth discovery, resource templates, and
change subscriptions are planned next; Phase 1 intentionally does not pretend
that a long-lived run is synchronous.

## Durable execution and receipts

The dispatcher leases one queued run at a time per thread. Before inference it
materializes the exact source and then atomically reserves bounded platform
spend. It sends Workers AI only bounded repository text and recent completed
conversation messages; provider logging is disabled when the configured AI
Gateway is used. Prompts and completions are not stored in usage or receipt
rows.

On success, one D1 batch records:

- the assistant message;
- `message.completed` and `run.completed` events;
- the terminal run state and estimated cost;
- reservation settlement;
- an immutable metadata-only execution receipt; and
- outbox delivery.

The public receipt includes the resolved compute profile and backend, driver,
model, estimated input/output tokens and cost, coarse compute usage, runner
version, and a SHA-256 receipt digest. Worker CPU is reported as zero when the
runtime cannot measure it; Forge does not invent precision.

If a dispatch lease expires before inference starts, the minute reconciler may
retry it. Inside one already-authoritative run, Instant retries exactly one
normalized provider timeout after a bounded jittered delay. Both calls keep the
same run/turn cache identity, input metering is conservative across attempts,
and `run.completed` records `provider_attempts`. Permanent provider errors,
invalid output, grounding failures, and persistence failures are never retried.
If the second provider attempt is still ambiguous, Forge marks the reservation
ambiguous and fails the run; the outbox never creates a second run.

## Workspace publication

Workspace publication stays entirely inside Forge. The trusted publisher
rechecks the accepted source ref against its exact SHA, reconstructs the one
`agent/<thread>/<run>` commit, and records the branch, native pull request,
artifacts, events, run settlement, and immutable publication receipt. The
branch and pull request are fenced by the same source-SHA comparison. A moved
base fails closed, and a cancellation that wins after branch creation removes
the unpublished branch before the outbox becomes cancelled.

The created pull request is a real Forge draft with preview deployment
suppressed. Forge refuses to merge it while `draft` is true; an authorized
reviewer can mark it ready through the pull-request update API before merging.
Replaying a completed publication returns its durable result without creating
another branch or pull request. No GitHub App, installation, token, API call,
or mirror commit participates in this path.

## Authentication and repository scope

The browser uses the signed-in Forge session. External integrations should use
a Forge personal access token or an agent service-principal API key. Service
principals have explicit per-repository grants, separately rotatable keys, and
audit attribution suitable for future Slack, Discord, and email connectors.

Relevant permissions are:

- `agent:read` for threads, events, runs, and receipts;
- `agent:message` for appending messages;
- `agent:run` for creating threads and other run controls;
- `agent:cancel` and `agent:approve` control interruptible Workspace runs and
  explicit approvals;
- `agent:write` is required in addition to repository write permission for
  Workspace Alpha; `agent:configure` remains reserved.

Thread, run, message, approval, event, reservation, and receipt records all
retain repository scope. Caller-supplied account IDs, provider credentials,
models, URLs, headers, or raw compute resources are never accepted.

## UI

The repository Code page includes a movable, resizable agent panel. Open it
with the Agent shortcut or `Command+.` / `Control+.`. The panel exposes Auto and
Instant, labels Workspace as coming soon, shows live durable events, and renders
the terminal execution receipt. It is shown only to signed-in users and pins
each message to the branch currently selected in the repository browser. Only
the last thread handle, an unaccepted draft, and panel geometry are stored in
browser memory; conversation content stays in Forge.

## Next profile

Workspace Alpha reuses the same thread, message, run, event, approval, artifact,
and receipt contract. General availability remains blocked on broader policy,
operational, and abuse-resistance evidence; the Alpha allowlist must not be
removed merely because the private execution path exists.

The first production dogfood policy is intentionally narrower than the general
Workspace contract: only the Forge repository, the owning Forge user,
`scripts/runner-release-inputs.test.mjs`, and its offline Node test command are
admitted. Repository and runner carry the same checked-in policy, and release
contracts test that they cannot drift independently. Expanding the repository,
user, path, command, or dependency-host set requires a reviewed source change
and new exact-version releases of both authority boundaries.
