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
30 changes: 30 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13261,3 +13261,33 @@ repository warnings only); the focused work-session suite passed 8 tests; the
full Vitest gate passed 1,316 tests with one intentional live skip; the fresh
production build succeeded; and the focused settings Playwright journey
passed.

---

## 2026-07-15 — Agent Studio identity, runtime, and client configuration

Audited the complete agent-configuration journey from fresh desktop and mobile
Playwright captures. Agent identity, workspace binding policy, execution
runtimes, MCP credentials, instance governance, and operational telemetry were
modeled correctly in data but split across ambiguous or duplicated surfaces.

Renamed the global profile home to Agent Studio and made it the editable source
of truth for identity and the single primary execution runtime. Profile detail
now reports runtime, binding, and MCP-client readiness, aggregates every linked
client by workspace, and deep-links into client creation with the correct
binding selected. Profile identity/execution edits synchronize to active
bindings without overwriting workspace-local policy.

Made the workspace Agent roster explicitly policy-only, collapsed dense policy
rows by default, and repaired the mobile action layout. Consolidated persistent
client credentials, personal tokens, session keys, scopes, rotation, and
revocation under Agent access; removed Developer clients from navigation and
redirected its legacy routes. Instance Administration remains governance and
Mission Control remains read-only operations.

Verification: lint and typecheck passed; the canonical serial Vitest gate
passed 1,318 tests with one intentional live-connector skip; and the fresh
production Playwright build passed all 45 desktop, mobile, accessibility, and
application journeys. Before/after evidence plus the UX health report are
preserved under `docs/audits/agent-studio-2026-07-15/`. Production verification
follows after tagging and deployment.
115 changes: 61 additions & 54 deletions docs/agents/overview.md

Large diffs are not rendered by default.

59 changes: 40 additions & 19 deletions docs/agents/profiles-and-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ An agent in Forge isn't a single row. It's a **three-tier** model:
1. A global **profile** — the agent's definition (who it is, what it
can do), owned by a user, independent of any workspace.
2. A per-workspace **binding** — a workspace adopting that profile,
with its own *policy* (capacity, capability overrides, dispatch
with its own _policy_ (capacity, capability overrides, dispatch
eligibility, engagement mode, approval gate).
3. **Instance policy** — the instance admin's governance layer:
sharing a profile to every workspace, or force-disabling it.
Expand All @@ -17,31 +17,37 @@ identity everywhere.
## Tier 1 — Profiles (the definition)

A **profile** (`AgentProfile`) is the source of truth for an agent's
identity: its `profileKey` (the stable cross-system handle, matching
the Hermes profile directory name), name, avatar, `provider`,
`runEngine`, default `runtimeId`, `baseCapabilities`, role, and
identity and execution: its `profileKey` (the stable cross-system handle,
matching the Hermes profile directory name), name, avatar, `provider`,
`runEngine`, zero-or-one primary `runtimeId`, `baseCapabilities`, role, and
template. It's owned by a user and lives outside any workspace.

`profileKey` is **unique per owner**, so two different users can each
own a `victor` without colliding.

Manage profiles at **`/settings/agents`** (the global, account-level
agents page). This is also where your profiles surface on
Manage profiles in **Agent Studio** at **`/settings/agents`** (the global,
account-level agents page). Its detail view reports runtime, workspace-binding,
and MCP-client readiness and is the only place identity/execution fields are
edited. This is also where your profiles surface on
[Mission Control](/guide/mission-control.html#my-agents).

Updating a profile synchronizes its identity and execution fields into every
active workspace binding. Binding policy such as capacity and capability
overrides is deliberately preserved.

## Tier 2 — Bindings (the policy)

A **binding** is an `Agent` row: a workspace adopting a profile via
`Agent.profileId`. Binding copies the profile's definition into the
workspace, then layers per-workspace **policy** on top:

| Binding policy | Column | What it does |
|---|---|---|
| Capacity | `maxConcurrent` | Cap on simultaneously-claimed issues (0 = unlimited) |
| Capability overrides | `capabilities` | Per-workspace tags (default: the profile's `baseCapabilities`) — feed `CAPABILITY_MATCH` |
| Auto-dispatch eligibility | `autoDispatchEligible` | When false, never auto-picked here — manual assignment only |
| Engagement mode | `engagementMode` | Per-binding default; null = inherit `Workspace.assignmentEngagementMode` |
| Approval gate | `requireApprovalBeforeStart` | Per-binding override of the workspace approval gate |
| Binding policy | Column | What it does |
| ------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------- |
| Capacity | `maxConcurrent` | Cap on simultaneously-claimed issues (0 = unlimited) |
| Capability overrides | `capabilities` | Per-workspace tags (default: the profile's `baseCapabilities`) — feed `CAPABILITY_MATCH` |
| Auto-dispatch eligibility | `autoDispatchEligible` | When false, never auto-picked here — manual assignment only |
| Engagement mode | `engagementMode` | Per-binding default; null = inherit `Workspace.assignmentEngagementMode` |
| Approval gate | `requireApprovalBeforeStart` | Per-binding override of the workspace approval gate |

Bind, set policy, and unbind from the workspace agents page at
**`/w/[slug]/settings/agents`**. The **catalog** there lists the
Expand All @@ -52,7 +58,7 @@ and `remove` — are workspace-admin-gated.
::: tip Unbind vs Delete
**Unbind** archives the binding (reversible) — runs, chats, and history are
preserved, and re-binding the same profile reuses the archived row.
**Delete** (the trash action beside Unbind) is a *smart remove*: it
**Delete** (the trash action beside Unbind) is a _smart remove_: it
hard-deletes a genuinely unused agent (no runs, comments, keys, or
assignments) and otherwise archives it — so a deletion can never cascade
away an agent's run history.
Expand All @@ -63,7 +69,7 @@ away an agent's run history.
Two governance levers belong to the instance admin (see
[Instance admin](/guide/instance-admin.html)):

- **`instanceShared`** — when set, the profile appears in *every*
- **`instanceShared`** — when set, the profile appears in _every_
workspace's bind-catalog, not just the owner's. This is how a shared
fleet agent becomes adoptable org-wide.
- **`disabledAt`** — a force-disable. A disabled profile (and all its
Expand All @@ -77,7 +83,7 @@ Two governance levers belong to the instance admin (see

## Requesting a profile

Defining a *new* profile from scratch is instance-admin-only — but any
Defining a _new_ profile from scratch is instance-admin-only — but any
member can **request** one:

1. A member calls `agentProfile.request` (the **Request a profile**
Expand All @@ -93,14 +99,29 @@ member can **request** one:
Profiles created directly by an instance admin skip this — they're
pre-approved at creation (`requestedById` stays null).

## MCP clients (the connection credentials)

MCP clients are **not execution runtimes**. A profile has at most one primary
runtime, while each workspace binding may have any number of linked `ApiKey`
credentials for Codex, Claude, Hermes, or other trusted MCP clients.

Create, inspect, rotate, revoke, and remove those credentials at
**`/w/[slug]/settings/access`**. Agent Studio aggregates the linked clients by
binding and deep-links into Agent access with the correct workspace agent
preselected. The former `/settings/clients` and
`/w/[slug]/settings/clients` inventory routes redirect to Agent access.

## How this composes with the rest

- **Engagement mode** — a binding's `engagementMode` sets the default
*intent* (Execute / Research / Review / Discuss) for work dispatched
_intent_ (Execute / Research / Review / Discuss) for work dispatched
to that agent in that workspace; null inherits the workspace default.
See [Engagement modes](/agents/engagement-modes.html).
- **Runtimes** — a profile points at a default `runtimeId` (the compute
host); the binding inherits it. See [Runtimes](/agents/runtimes.html).
- **Runtimes** — a profile points at zero-or-one primary `runtimeId` (the
execution host); every active binding inherits profile execution changes.
See [Runtimes](/agents/runtimes.html).
- **MCP clients** — each binding can hold zero-or-many linked credentials;
these authenticate clients but do not replace the primary execution runtime.
- **Auto-dispatch** — `autoDispatchEligible` and the binding's
`capabilities` feed the workspace dispatcher; `autoDispatchMode`
(which agent gets picked) is a different axis from engagement mode
Expand Down
32 changes: 20 additions & 12 deletions docs/agents/runtimes.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# Runtimes

A **Runtime** is the compute environment that hosts one or more agents.
Where `Agent` describes *who* (a profile, a webhook secret, a runtime
mode) and `runtimeMode` describes *how* the agent stays online, `Runtime`
describes *where the work physically happens*.
Where `Agent` describes _who_ (a profile, a webhook secret, a runtime
mode) and `runtimeMode` describes _how_ the agent stays online, `Runtime`
describes _where the work physically happens_.

::: info Runtime versus MCP client
An Agent Studio profile selects **zero or one primary execution runtime**.
Codex, Claude, Hermes, and custom MCP clients connect with separate linked
credentials in the workspace's **Agent access** page; a binding can have many
of those clients. Adding an MCP client never changes the profile's runtime.
:::

::: tip Distinct from `runtimeMode`
`Agent.runtimeMode` is `PERSISTENT | EPHEMERAL` and lives on the agent
Expand All @@ -23,11 +30,11 @@ enum RuntimeKind {
}
```

| Kind | Endpoint | Presence model |
|---------------|-----------------|------------------------------------------------------|
| `LOCAL_DAEMON`| no `endpoint` | Daemon subscribes to `/api/plugins/events` SSE and pulls work. |
| `REMOTE_HTTP` | webhook URL | Forge pushes events outbound over HTTPS with HMAC. |
| `CLOUD` | reserved | Not yet implemented. |
| Kind | Endpoint | Presence model |
| -------------- | ------------- | -------------------------------------------------------------- |
| `LOCAL_DAEMON` | no `endpoint` | Daemon subscribes to `/api/plugins/events` SSE and pulls work. |
| `REMOTE_HTTP` | webhook URL | Forge pushes events outbound over HTTPS with HMAC. |
| `CLOUD` | reserved | Not yet implemented. |

`Runtime.heartbeatAt` is bumped by the runtime itself (not its agents) —
an idle runtime can still be alive while none of its agents have done
Expand All @@ -53,8 +60,8 @@ columns.
`LOCAL_DAEMON` rows. The detail page also shows whether the runtime
declares `terminal`, `filesystem`, and `git` access, plus the latest
sanitized runtime version/environment metadata when the host reports it.
- **Agent detail page** — small Runtime card that click-throughs to the
runtime detail.
- **Agent Studio profile detail** — readiness summary plus an editable primary
Runtime assignment that synchronizes to active workspace bindings.
- **Mission Control agents tab** — compact `RuntimeChip` next to the
runtime-mode pill.

Expand Down Expand Up @@ -182,7 +189,7 @@ reply via `chat.finalizeDraft` — no daemon crash.

- **`CHAT_MESSAGE_POSTED` (role=USER)** — reads `body` + `context`
directly from the SSE payload, calls `agent.context.bundle({
threadId })` for thread history + linked-issue summary +
threadId })` for thread history + linked-issue summary +
workspace, inlines image / PDF / text attachments via
`attachments.getInline`, and spawns the provider adapter with the
bundle as system prompt and the user message as a content-block
Expand Down Expand Up @@ -215,13 +222,14 @@ they observe `autoTransitionedTo` in the payload.
:::

::: warning v1 limitations

- Login takes URL + token directly (no OAuth device-code flow yet).
- The AGENT_ASSIGNED loop only auto-runs for `CLAUDE` provider
agents; other providers receive a placeholder comment.
- If `Workspace.startedStatusId` is not configured, agents or daemons
should use `statuses.list({ category: "IN_PROGRESS" })` and transition
explicitly when Execute-mode work actually starts.
:::
:::

## Token usage on AgentRun

Expand Down
106 changes: 106 additions & 0 deletions docs/audits/agent-studio-2026-07-15/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Agent Studio configuration audit — 2026-07-15

## Outcome

Forge now presents agent configuration as five explicit, non-overlapping
surfaces:

- **Agent Studio** owns the durable identity, provider, prompt, base
capabilities, and zero-or-one primary execution runtime.
- **Workspace Agent roster** binds that identity into a workspace and owns only
local capacity, routing eligibility, engagement, approval, and capability
overrides.
- **Workspace Agent access** owns zero-or-many MCP client credentials per
binding, plus personal and session credentials, scopes, rotation, and
revocation.
- **Instance Administration** owns approval, instance sharing, disabling, and
removal.
- **Mission Control** remains read-only operational telemetry for runtime
health, capacity, queues, runs, and attention.

This makes the core relationship explicit:

```text
Agent profile
├── primary execution runtime: 0..1
├── workspace binding: 0..n
│ └── MCP client credentials: 0..n
└── instance governance policy: 1
```

The previous Agent Clients inventory has been retired as an independent
surface. Its routes redirect to Agent access so saved links keep working while
credential creation and credential lifecycle have one source of truth.

## Evidence

The audit used a fresh production-mode Playwright build with seeded data at
1440×1000 and 390×844. The accepted current-state captures are in
[`after/`](./after/); the original captures are preserved in
[`before/`](./before/) for direct comparison.

Key accepted captures:

- `after/01-global-agent-profiles.png` — Agent Studio inventory
- `after/02-create-agent-profile.png` — creation with primary runtime
- `after/03-agent-profile-detail.png` — readiness and connection model
- `after/04-edit-agent-identity.png` — editable identity and execution
- `after/05-add-mcp-client.png` — deep-linked, preselected MCP client wizard
- `after/07-workspace-agent-bindings.png` — collapsed workspace roster
- `after/08-workspace-agent-policy-expanded.png` — policy on demand
- `after/09-agent-access.png` — consolidated credential lifecycle
- `after/10-instance-agent-policy.png` — instance governance
- `after/11-mission-control.png` — read-only operations
- `after/12`–`14` — mobile Agent Studio, detail, and workspace roster

## Numbered walkthrough health

1. **Find the agent definition — healthy.** “Account & identity” no longer
claims shared profiles are personal settings, and Agent Studio explains its
identity/runtime/workspace remit at entry.
2. **Create a profile — healthy.** Creation now includes the primary execution
runtime and explains that MCP clients are configured separately. Required
identity fields and the existing instance-admin gate remain clear.
3. **Understand readiness — healthy.** The profile begins with three explicit
cards for runtime, workspace bindings, and MCP clients. Missing execution or
access is visible without inferring it from an empty field.
4. **Edit identity and execution — healthy.** Name, avatar, description,
provider, run engine, base capabilities, and the single runtime can be
edited together. Identity/execution changes propagate to active workspace
bindings while workspace policy remains local.
5. **Attach multiple clients — healthy.** Each workspace binding aggregates all
linked MCP client credentials and opens Agent access with that binding
preselected. Adding another client never replaces the execution runtime.
6. **Tune workspace behavior — healthy.** Roster rows default to compact status
summaries; policy expands only when requested. The large always-visible
three-step explainer and policy grids no longer dominate the page.
7. **Manage credentials — healthy.** Client creation, scopes, inspection,
rotation, revocation, and deletion now share one Agent access surface. The
separate Developer clients navigation and inventory were removed.
8. **Govern the instance — healthy.** Instance Administration remains the only
place for cross-workspace sharing, approval, disable, and removal decisions.
9. **Operate the fleet — healthy.** Mission Control remains visibly read-only
and reports runtime attention, capacity, runs, queues, presence, and recent
activity without becoming a fourth configuration surface.
10. **Use the flow on mobile — healthy after repair.** Settings navigation stays
collapsed, readiness cards stack, the creation callout reflows, and roster
actions remain in a readable action row instead of narrow text columns.

## Accessibility and usability notes

- Existing design tokens, focus-ring utilities, semantic buttons, switch roles,
`aria-expanded`, `aria-current`, and labeled settings search were preserved.
- Progressive disclosure reduces vertical scanning and interaction cost but
keeps all binding actions keyboard reachable.
- Readiness does not rely on color alone: each card includes a label, value,
status icon, and explanatory text.
- The Playwright walkthrough validates visible behavior and responsive layout;
it does not replace a full screen-reader or automated WCAG audit.

## Verification contract

The focused router coverage proves that profile edits synchronize identity and
execution fields to active bindings and that a profile aggregates multiple MCP
clients. The Playwright journey exercises desktop and mobile entry, creation,
editing, client deep-linking, collapsed/expanded workspace policy, instance
governance, and Mission Control.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading