Skip to content
Open
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
15 changes: 13 additions & 2 deletions docs/guides/user/bring-your-own-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ image: ghcr.io/fullsend-ai/fullsend-sandbox:latest # Pin to a digest before CI
policy: policies/base.yaml
providers:
- vertex-ai
role: my-agent
slug: my-org-my-agent # GitHub App identity; convention: <org>-<role> (see Custom agent identity)
role: triage # a role your mint SERVES — not the agent's name (see note below)
slug: my-org-my-agent # install-time App discovery only; the mint never reads it
trigger: |
event.entity.kind == "work_item"
&& event.transition.kind == "label_changed"
Expand All @@ -96,6 +96,16 @@ trigger: |
timeout_minutes: 15
```

> **`role` is not the agent's name.** The agent's name is `name:` in its `.md`;
> `role:` selects which GitHub App and permissions the mint issues. On the
> default (hosted) mint, `role:` must be one of the built-in roles it serves —

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] technical accuracy in documentation

The callout states role: must be one of the built-in roles triage, coder, review, retro, prioritize, fullsend — omitting fix. A user with a fix-like agent who sets role: fix would believe this is invalid based on the docs, when fix is a canonical built-in role that the hosted mint accepts.

Suggested fix: Add fix to the enumerated list.

> `triage`, `coder`, `review`, `retro`, `prioritize`, `fullsend`. Pick the one
> whose permissions fit what your agent does (a code-writing agent uses
> `role: coder`). A made-up role like `role: my-agent` returns `403` from the
> mint. To use a *new* role or your *own* identity, you need your own mint —
> see [Custom Agent Identity](custom-agent-identity.md).


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] trailing whitespace / blank lines

Double blank line after the role blockquote callout. Codebase convention is a single blank line between elements.

Suggested fix: Remove one of the two blank lines.

**`providers/vertex-ai.yaml`** — provider definition (declares a provider by name and type):
```yaml
name: vertex-ai
Expand Down Expand Up @@ -348,6 +358,7 @@ allowed_remote_resources:
|---------|-----|
| Agent crashes at 0s | Sandbox can't reach Vertex AI — verify that `providers/vertex-ai.yaml` is listed in your harness `providers:` and that `ANTHROPIC_VERTEX_PROJECT_ID`/`CLOUD_ML_REGION` are set (in your `--env-file` for local runs, or in the workflow `env` block for CI) |
| "role field is required" | Add `role:` to harness |
| `403` / "role not allowed" from the mint | Your `role:` is not one the mint serves. On the hosted mint use a built-in role (`triage`, `coder`, `review`, `retro`, `prioritize`, `fullsend`); for a custom role, point `FULLSEND_MINT_URL` at your own mint — see [Custom Agent Identity](custom-agent-identity.md) |
| Agent can't find input files | Pre-script output paths must match `host_files` entries |
| Provider blocks requests | Check that the required provider profile is listed in `providers:` and exists in the `providers/` directory |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] internal consistency

The troubleshooting table 403 row lists the same incomplete built-in role set without fix.

Suggested fix: Add fix to the parenthetical list of valid built-in roles.

| Schema validation fails | Compare the sandbox output (`$FULLSEND_OUTPUT_DIR/<result>.json`) against the schema referenced in `validation_loop` / `FULLSEND_OUTPUT_SCHEMA`; re-run with `--keep-sandbox` to inspect |
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/user/building-custom-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ model: opus
effort: high # optional: low, medium, high, xhigh, max (claude runtime only)
image: ghcr.io/fullsend-ai/fullsend-sandbox:latest
policy: policies/my-agent.yaml
role: my-agent
role: triage # a role the mint serves — not the agent's name (see Custom Agent Identity)

providers:
- vertex-ai # Required: model access (Anthropic API + GCP)
Expand Down
89 changes: 77 additions & 12 deletions docs/guides/user/custom-agent-identity.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,94 @@
# Custom Agent Identity

By default, agents authenticate using shared fullsend GitHub Apps via the `slug` field in the harness. Each agent's `role` maps to a GitHub App installation managed by the hosted mint service.
When an agent acts on GitHub — commits, comments, reviews, status checks — it
does so as a **GitHub App**. Which App, and what that App is allowed to do, is
decided by one field in your harness: **`role`**.

A standalone mint makes sense when:
```yaml
role: triage # ← decides identity AND permissions at the mint
slug: my-org-triage # ← install-time hint only; the mint never reads it
```

- **Custom permissions** -- your agent needs GitHub App permissions beyond what the shared Apps grant (e.g., write access to packages or deployments).
- **Compliance** -- your organization requires that GitHub App credentials stay within your own infrastructure.
- **Branding** -- you want agent actions (commits, comments, status checks) to appear under your own GitHub App name and avatar.
The mint service maps `role` to a GitHub App (its ID + private key) and to a
permission ceiling, then issues a token scoped to your repo. `slug` only helps
`fullsend github setup` find or name the App at install time — it is **not**
what authenticates your agent, and changing it does not change identity or
permissions. If you set a `role` the mint doesn't serve, you get a `403`, not a
new identity.

If none of these apply, the shared Apps work without extra setup -- set `slug` in your harness and go. To run your own, follow the [Standalone mint guide](../infrastructure/standalone-mint.md).
So the real question is: **whose mint issues your token?**

Once your standalone mint is running, configure your agent to use it:
## Two paths, one decision

1. **Reference your role in the harness:**
| | Default (hosted) mint | Your own mint (standalone) |
|---|---|---|
| **URL** | `https://mint.fullsend.sh` (default) | your `FULLSEND_MINT_URL` |
| **Roles you can use** | a **fixed** built-in set — `triage`, `coder`, `review`, `retro`, `prioritize`, `fullsend` | those built-ins **plus** any custom role you define |
| **Identity** | the shared fullsend App for that role (e.g. `fullsend-ai-triage[bot]`) | **your** GitHub App — your name, your avatar |
| **Custom permissions** | no — each role's ceiling is fixed | yes — `security_events:write`, `deployments:write`, anything the GitHub API allows |
| **Who sets it up** | nobody — it just works | you (create App → install → register the role) |

**The default mint cannot mint a new identity for you.** It serves a fixed set
of Apps that fullsend operates (see [why](../infrastructure/standalone-mint.md)).
Picking a `role:` it doesn't serve — or a custom `slug:` — will not create one;
it produces the `403` above.

## Most customization needs no custom identity

Before reaching for your own mint, check whether you actually need a new
identity. You usually don't:

- **Changing behavior** — model, timeout, skills, prompt, env — keeps a
built-in `role:`. Use [`base:` composition](customizing-agents.md#configuration-with-base-composition);
the agent still runs as that role's App.
- **A brand-new agent** (its own trigger, scripts, schema) can still run on the
hosted mint — set its `role:` to the built-in role whose permissions match
what it does. A code-writing agent uses `role: coder`; a triage-like agent
uses `role: triage`. The agent's own name lives in `name:` in its `.md`, not
in `role:`.

> **Rule of thumb.** Pick the built-in role whose permission ceiling is the
> closest fit for what your agent needs to do. You only need your own mint when
> **no** built-in role fits — because you need a distinct identity, or
> permissions no built-in role has.

## When you do need your own mint

Choose a standalone mint when one of these is true:

- **Custom permissions** — your agent needs GitHub App permissions beyond any
built-in role (for example, write access to packages, deployments, or
security events).
- **Custom identity / branding** — you want actions to appear under your own
GitHub App name and avatar, not the shared fullsend App.
- **Compliance** — your organization requires GitHub App credentials to stay
inside your own infrastructure.

Set it up, then point your repo at it:

1. **Define the role and App on your mint** — follow the
[Standalone mint guide](../infrastructure/standalone-mint.md): create the
GitHub App, install it, store its PEM, and register the role's permissions
(`CUSTOM_ROLE_PERMISSIONS`, or `fullsend mint add-role`).

2. **Reference the role in your harness:**
```yaml
role: my-role
slug: my-org-my-role
role: my-role # a role YOUR mint serves
slug: my-org-my-role # install-time App discovery; still not read by the mint
```

2. **Set `FULLSEND_MINT_URL`** in your repo to point to your standalone mint.
3. **Point your repo at your mint** — set `FULLSEND_MINT_URL` to your mint's
URL. Without this, tokens are requested from the hosted mint, which does not
serve `my-role`.

When configured with `FALLBACK_MINT_URL`, the standalone mint serves custom roles locally while proxying unhandled roles to the hosted mint (see [Standalone mint — Fallback proxy behavior](../infrastructure/standalone-mint.md#fallback-proxy-behavior)).
> **Tip: adopt gradually.** With `FALLBACK_MINT_URL`, your standalone mint
> serves your custom roles locally and proxies the built-in ones to the hosted
> mint — so you can start with a single custom role without disrupting existing
> agents. See [Standalone mint — Fallback proxy behavior](../infrastructure/standalone-mint.md#fallback-proxy-behavior).

## See also

- [Bring Your Own Agent](bring-your-own-agent.md) — end-to-end guide for building and registering agents
- [Configuring Agent Behavior](customizing-agents.md) — change model, skills, and env while keeping a built-in role
- [Standalone Mint](../infrastructure/standalone-mint.md) — full standalone mint setup guide
- [Harness Field Reference](../../reference/harness-reference.md) — complete harness YAML reference including `role` and `slug`
6 changes: 5 additions & 1 deletion docs/guides/user/customizing-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,11 @@ Reference the skill in your harness's `skills:` list. The skill is available to

## Agent roles

Each agent role has its own identity, permissions, and purpose:
On the hosted mint, agents run as one of a **fixed** set of built-in roles.
Each role is a GitHub App identity with a fixed permission ceiling. An agent's
name is separate from its role — the `code` and `fix` agents both run as the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] technical accuracy in documentation

The new text states 'the code and fix agents both run as the coder role.' While fix shares the coder GitHub App and PEM, fix is a distinct entry in canonicalRolePermissions with a different permission ceiling (fix lacks checks:read). The built-in fix harness uses role: fix, not role: coder.

Suggested fix: Consider rewording to 'the code and fix agents both authenticate as the coder GitHub App' to avoid implying they share the same role entry.

`coder` role. To pick a role for a custom agent, or to use your own identity or
a custom role, see [Custom Agent Identity](custom-agent-identity.md).

| Role | GitHub App | Purpose |
|------|------------|---------|
Expand Down
7 changes: 4 additions & 3 deletions docs/guides/user/customizing-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ adding skills via harness, extending the sandbox image, disabling agents.

## Bring Your Own Agent

When you need a completely new agent — with its own trigger, scripts,
output schema, and possibly its own GitHub App identity — build one from
scratch:
When you need a completely new agent — with its own trigger, scripts, and
output schema — build one from scratch. It still runs on the hosted mint if it
assumes a built-in `role:`; a distinct GitHub App identity requires your own
mint (see [Custom Agent Identity](custom-agent-identity.md)):

```
.fullsend/
Expand Down
8 changes: 4 additions & 4 deletions docs/reference/harness-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Complete reference for all fields available in a fullsend harness YAML file. For
```yaml
# ── Required ──────────────────────────────────────────────────
agent: agents/my-agent.md # Path to agent definition
role: my-agent # Role name (lowercase letter first, then a-z, 0-9, _, -; no double hyphens)
role: triage # A role the mint serves (built-in on the hosted mint); not the agent's name. Format: lowercase letter first, then a-z, 0-9, _, -; no double hyphens

# ── Identity & metadata ──────────────────────────────────────
slug: my-org-my-role # GitHub App identity (convention: <org>-<role>)
slug: my-org-my-role # install-time App discovery (convention: <org>-<role>); not read by the mint

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] inline comment capitalization

The inline YAML comment for slug starts with a lowercase letter (install-time App discovery). Every other inline comment in this reference YAML block starts with an uppercase letter.

Suggested fix: Capitalize the first word: Install-time App discovery ...

description: One-line summary # Human-readable description
doc: docs/agents/my-agent.md # Source-repo-only; not resolved at runtime
trigger: "event.entity.kind == 'work_item'" # Optional CEL expression over NormalizedEvent (see CEL Triggers Reference)
Expand Down Expand Up @@ -126,9 +126,9 @@ security:

Most fields are self-explanatory from the inline comments above. This section expands on fields where additional context helps.

**`role`** — The agent's identity within fullsend. Dispatch uses the role to match config-registered agents to built-in defaults (same-name config agents take precedence). The role also determines which GitHub App credentials the mint service issues.
**`role`** — The agent's identity within fullsend. Dispatch uses the role to match config-registered agents to built-in defaults (same-name config agents take precedence). The role also determines which GitHub App credentials **and permissions** the mint service issues. It must be a role the mint serves: on the hosted mint that is the fixed built-in set (`triage`, `coder`, `review`, `retro`, `prioritize`, `fullsend`); custom roles require your own mint. An unserved role returns `403`. See [Custom Agent Identity](../guides/user/custom-agent-identity.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] technical accuracy in documentation

The role field description lists the hosted mint's built-in set without fix. Since fix is a canonical built-in role and the existing fix agent harness uses role: fix, this reference doc would incorrectly tell users that role: fix requires a custom mint.

Suggested fix: Add fix to the built-in role list.


**`slug`** — Maps to a GitHub App installation. The `<org>-<role>` convention keeps slugs unique when multiple orgs share a mint. For custom GitHub App identity, see [Custom Agent Identity](../guides/user/custom-agent-identity.md).
**`slug`** — Install-time hint used by `fullsend github setup` to find or name the GitHub App. The `<org>-<role>` convention keeps slugs unique when multiple orgs share a mint. The **mint does not read `slug`** when issuing a token — identity and permissions come from `role`, so changing `slug` alone changes neither. For a custom GitHub App identity, see [Custom Agent Identity](../guides/user/custom-agent-identity.md).

**`doc`** — Path to a human-readable document describing the agent's purpose and design. Resolved in the source repo only; the runtime ignores it. Useful for documentation indexes and discoverability.

Expand Down
Loading