# Agent Design Patterns
Source: https://docs.agentuse.io/guides/agent-design-patterns
Best practices for building production-ready AgentUse agents
## Core Design Principles
### Writing Instructions as SOPs
Writing agent instructions is like creating a Standard Operating Procedure (SOP) for an employee. Just as SOPs provide clear, repeatable instructions for human workers, agent instructions should be precise, actionable, and comprehensive.
When crafting agent instructions, think of yourself as a manager writing detailed procedures that any employee could follow:
* **Be specific**: Like an SOP, leave no room for ambiguity
* **Include all context**: Provide all necessary information upfront
* **Define success criteria**: Clearly state what "done" looks like
* **Handle edge cases**: Anticipate and document how to handle exceptions
### 1. Non-Interactive by Design
AgentUse agents run without interactive prompts, making them perfect for automation, CI/CD pipelines, and cron jobs.
Agents are designed to:
* Run autonomously from start to finish
* Complete tasks without user intervention
* Work in headless environments
* Integrate into automated workflows
Because nobody is watching the run, the rehearsal has to happen beforehand: [`agentuse test`](/guides/testing-agents) exercises the whole SOP, including approval branches, with side effects fabricated.
### 2. Agent as Delegated Employee
Think of agents as specialized employees you delegate work to. Once you hand off a task with clear instructions, they work autonomously until completion, just like delegating to a trusted team member.
This delegation model means:
* **Set and forget**: Give clear instructions and let the agent work independently
* **No micromanagement**: The agent handles the task from start to finish
* **Clear handoff**: Define input requirements and expected outputs
* **Trust the process**: Like a well-trained employee, the agent follows your SOPs
### 3. Communication Through Tools
Just as employees communicate and hand off work through tools like Slack and Notion, agents should use MCP servers and external integrations to report progress and deliver results.
Agents communicate through:
* **Status updates**: Use Slack MCP to send progress notifications
* **Documentation**: Update Notion databases with results
* **Handoffs**: Save artifacts to shared filesystems for other agents
* **Reporting**: Post summaries to webhooks or APIs
This approach mirrors how remote teams collaborate, asynchronously through shared tools rather than constant direct interaction.
### 4. Separation of Concerns
Use sub-agents to separate different responsibilities, keeping each agent focused on a single task.
Each agent should:
* Have a single, clear purpose
* Delegate complex subtasks to sub-agents
* Use appropriate models for the task (Haiku for simple tasks, Sonnet for complex reasoning)
* Maintain clear boundaries between concerns
## Implementation Patterns
### Multi-Agent Workflow Pattern
Complex tasks can be decomposed into specialized agents that work together through sub-agent composition. This mirrors how organizations structure teams, each specialist handles their domain, communicating through established channels.
#### Example: Content Pipeline
Gathers information using web search or MCP tools
```markdown research.agentuse theme={"system"}
---
model: anthropic:claude-haiku-4-5
mcpServers:
filesystem:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./research"]
---
You are a research specialist. Find and save relevant information.
## Task
1. Research the given topic thoroughly
2. Save findings to research folder
3. Return key insights summary
```
Creates content based on research
```markdown writer.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
---
You are a content writer. Create engaging, accurate content.
## Task
1. Review provided research
2. Create well-structured content
3. Ensure factual accuracy
```
Coordinates the workflow
```markdown orchestrator.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./research.agentuse
maxSteps: 50
- path: ./writer.agentuse
maxSteps: 100
---
You coordinate content creation workflow.
## Task
1. Use research agent to gather information
2. Pass findings to writer agent
3. Review and finalize output
```
### State Management with External Systems
Since AgentUse agents are stateless between runs, use MCP servers to manage state:
```yaml notion-state.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
notion:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-notion"]
requiredEnvVars: ["NOTION_TOKEN"]
---
You track workflow state in Notion.
## Task
1. Check current state in Notion database
2. Process next pending item
3. Update state after completion
```
```yaml file-state.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
filesystem:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./state"]
---
You manage state using local files.
## Task
1. Read state from state/current.json
2. Process based on current state
3. Write updated state back
```
### Error Handling
Build resilient agents with proper error handling:
```markdown robust-agent.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./validator.agentuse
- path: ./processor.agentuse
- path: ./error-handler.agentuse
---
You execute tasks with comprehensive error handling.
## Error Handling Strategy
1. Validate input with validator agent
2. If validation fails, use error-handler to log and notify
3. Process with processor agent
4. If processing fails, use error-handler for recovery
5. Always provide clear status at completion
```
### Chain of Responsibility
Process data through a sequential pipeline where each agent handles a specific transformation step:
```markdown chain-pipeline.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./validator.agentuse
- path: ./transformer.agentuse
- path: ./publisher.agentuse
---
You coordinate a data processing pipeline.
## Processing Pipeline
1. Use validator agent to validate input data
2. Pass validated data to transformer agent for processing
3. Send transformed data to publisher agent for final output
4. Return confirmation once all steps complete successfully
```
### Conditional Routing
Route requests to different handlers based on complexity or type:
```markdown conditional-router.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./simple-handler.agentuse
- path: ./complex-handler.agentuse
---
You route requests to appropriate handlers based on complexity.
## Routing Strategy
1. Analyze the incoming request complexity
2. For simple requests (< 3 steps), use simple-handler agent
3. For complex requests (>= 3 steps), use complex-handler agent
4. Return the handler's response with routing decision details
```
### Retry with Fallback
Implement resilient processing with automatic fallback on failures:
```markdown retry-fallback.agentuse theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./primary-agent.agentuse
- path: ./fallback-agent.agentuse
---
You ensure task completion through retry and fallback mechanisms.
## Execution Strategy
1. Attempt task with primary-agent first
2. If primary-agent succeeds, return its results
3. If primary-agent fails or times out, use fallback-agent
4. Log which path was taken and why
5. Always provide task results, regardless of path taken
```
# Agent Revisions
Source: https://docs.agentuse.io/guides/agent-revisions
Safely improve an agent from its source or the evidence in a completed or approval-paused run
AgentUse can turn an agent's current source or the evidence from a real run into
a reviewable change. Start a revision from an agent that has never run, a
completed run, a failed run, or a run paused at an approval gate. The revision
changes future runs; it does not rewrite or resume an originating run.
## Start a revision
Open the run in the dashboard and choose **Revise agent file**. For an agent
that has never run, open its detail page and start the revision there. Describe
the behavior you want to fix or improve, choose the authoring model, and start
the revision.
AgentUse creates a durable internal session linked to the originating run when
one exists. The reviser compares the current agent source, the available run
transcript, and a sanitized, read-only view of the project. If one material
decision is missing, it asks for that decision inside the same session instead
of guessing.
Only one active revision can belong to an originating run at a time. Return to
the origin session to see its current revision and revision history.
## Review the result
The reviser returns one of two outcomes:
* a validated source proposal, with the source diff and any capability changes
* a `no-agent-change` diagnosis explaining why changing the agent is not the
right response to the run
Review the proposal from the internal revision session. You can apply it,
request changes and continue the same session, or discard it. A no-change
diagnosis can likewise be accepted or reconsidered.
Use **Copy prompt for Coding Agent** when the work belongs in project code or a
custom integration rather than in the agent file.
## Write safety and recovery
Nothing changes the agent source until an operator applies the proposal.
AgentUse validates the proposed source and displays capability changes before
the write. A source-hash check rejects the apply if the agent changed after the
proposal was created, so a revision cannot overwrite newer work. The accepted
replacement is atomic.
After an apply, **Restore previous source** puts back the immediately preceding
agent source. The revision session and originating run retain durable links so
the diagnosis, proposal, decision, and restore path remain inspectable.
## Find revision sessions
The Sessions list and feed label these AgentUse-owned jobs as **internal
revision** and group them under **Internal revisions**. Their titles read
**Revising *agent***, and each links back to the originating run. An agent's
**Revisions** tab collects its revision history.
Internal revision sessions are different from delegated subagents and automated
Judge sessions. They are an operator-started workflow for changing an agent's
future behavior.
Agent revision is unavailable when `serve.hideAgentSource` or
`--hide-agent-source` is enabled. A deployment that does not expose agent
source cannot review or apply source revisions.
See [Session Logs](/guides/session-logs) for the complete run record and
[Operations Dashboard](/guides/serve-dashboard) for the surrounding workflow.
# Approval Gates
Source: https://docs.agentuse.io/guides/approval-gates
Pause an agent run for human review, then approve, reject, or comment from the AgentUse approval dashboard
Approval gates let an agent prepare work, pause before finalizing it, and continue only after a reviewer approves, rejects, or comments.
Every run is a session. The review surface is the unified **session page** at `/sessions/` in `agentuse serve`: it shows the run log, and when the session is suspended on an approval gate it also offers approve / reject / comment right there. `/approvals` remains as a filtered list of sessions currently waiting for review, and each row links to the session page. Slack is optional: it can notify reviewers and link them into the session page, but Slack is not where approval state lives.
## How It Works
1. Add `approval: true` to the agent frontmatter.
2. Run `agentuse serve`.
3. The agent works normally until it reaches the approval point.
4. AgentUse suspends the session on a pending approval gate.
5. Reviewers open the session page (`/sessions/`), either from `/approvals` or from a tokenized link.
6. A reviewer approves, rejects, or comments.
7. AgentUse resumes the suspended session with the reviewer result.
8. After the session finishes, reviewers can send follow-up instructions from the same session page to continue the session with its existing context.
A leaf agent's approval gate works the **same whether the agent is run directly or delegated by a `type: manager`** agent. See [Approval in delegated sub-agents](#approval-in-delegated-sub-agents) below.
## Create an Agent with Approval
Use the smallest possible config:
```md theme={"system"}
---
model: anthropic:claude-sonnet-5
approval: true
---
Write a polished launch email from the user request.
```
The markdown body stays focused on the work. You do not need to write instructions like "wait for approval before publishing."
If an approval should expire, set a timeout:
```yaml theme={"system"}
approval:
timeout: 24h
```
By default, approvals do not expire.
## Define the Approval Boundary
Approval gates are agent-driven: the agent calls the internal `await_human` tool when it reaches the point where review is needed. AgentUse injects the approval mechanism, but your agent instructions can still define the policy boundary for your workflow.
Write the boundary in business terms. Describe what the agent may prepare without approval, and what it must not finalize until approval is granted.
For a social publishing agent:
```md theme={"system"}
---
model: anthropic:claude-sonnet-5
approval: true
channels:
slack:
events: [approval]
---
Draft the social post and save any working files under `.agentuse/tmp/`.
You may create drafts, previews, and local artifacts without approval.
Before scheduling or publishing the post through any external service, request approval with:
- a short summary of the post
- the final post text
- the target account or channel
- the scheduled time, if any
- any risks or assumptions
```
For a release agent:
```md theme={"system"}
---
model: anthropic:claude-sonnet-5
approval:
timeout: 24h
---
Prepare the release notes and open a draft pull request if needed.
Do not publish the package, tag the release, merge the PR, or announce the release until the approval gate is approved.
```
Good approval boundaries usually separate reversible preparation from external side effects:
* Usually safe before approval: local temp files, drafts, previews, dry runs, summaries, draft PRs
* Usually approval-required: publishing, sending email, scheduling posts, deploying, merging, deleting, charging, or changing production/external state
* If unsure, ask for approval before the action
## Gated commands (mechanical enforcement)
The boundary above is guidance the model follows. For irreversible **bash commands** you can also enforce it mechanically, so the command cannot run before you approve it even if the model tries. List those commands under `tools.bash.gated`:
```yaml theme={"system"}
model: anthropic:claude-sonnet-5
tools:
bash:
commands: # auto-run, no approval
- "birdc read *"
- "birdc search *"
gated: # run only after you approve the exact action
- "birdc reply *"
```
Read it as: `commands` is what the agent can do; `gated` is what it can't do without you. A gated command is still allowed to run (the effective allowlist is `commands` plus `gated`), but only after a human approves the exact action. A command matching both lists is gated (gated wins), so a broad `birdc *` in `commands` cannot un-gate `birdc reply *`.
Declaring `gated` enables the approval machinery automatically, you do not also need `approval: true`. For a plain yes/no decision, the agent emits `await_human` and the gated command together. AgentUse attaches the exact command to the request, blocks it from executing, and lets the agent re-issue it only after you approve.
The guarantee is two-fold, enforced per action (not once per session):
1. A gated command never runs before approval.
2. A gated command never runs anything other than what you approved. Approval binds to the exact complete shell command shown in `changes[]`; payload text by itself grants nothing. If the agent revises the command or its payload, the old approval no longer covers it and it must re-gate.
3. Each approved entry is one-shot. It is consumed before dispatch, so an ambiguous failed external action is never retried silently. Listing the same exact command twice authorizes two executions.
Notes:
* **You rarely hand-write this.** Skills that ship posting commands, the interactive command prompt, and generated agent files add `gated` for you. `agentuse doctor ` also flags an allowlisted command that looks irreversible (`reply`, `post`, `delete`, `git push`, `curl -X POST`, ...) but is not gated. AgentUse never auto-gates from a keyword guess, it only suggests.
* **Plain gates auto-attach the command.** Emit `await_human` and the exact gated bash command in the same model step. The command is shown to the reviewer but remains blocked until approval; after approval the agent re-issues it once. Non-gated tools still cannot ride beside a gate.
* **Pick gates scope actions explicitly.** Give each `changes[]` action an `optionId` referencing the corresponding `options[].id`. When `content` is an executable command, also set `displayContent` to the exact human-facing post, reply, message, or body. The reviewer sees the business content first with the command de-emphasized inside the same option. Approval grants only the selected option plus any action with no `optionId`. This is the safe one-approval pattern for choosing among several irreversible commands.
* **Show the complete command.** Whether auto-attached or option-scoped, the lease covers the exact executable command (`birdc reply "text"`), not payload text alone. For browser automation, gate and show the step that carries the words (`agent-browser type "..."`), not a contentless click.
* **Unattended runs suspend only on a declared gate**, never on a tooling question. You approve outcomes, not commands.
## Start the Server
Start the AgentUse daemon:
```bash theme={"system"}
agentuse serve
```
Open the sessions dashboard (every run) or the approvals view (sessions waiting for review):
```text theme={"system"}
http://127.0.0.1:12233/sessions
http://127.0.0.1:12233/approvals
```
Both link into the per-session page at `/sessions/`.
If reviewers open links from another machine, start `serve` with a reachable public URL:
```bash theme={"system"}
agentuse serve --public-url https://agentuse.mycompany.com
```
AgentUse runs one serve daemon at a time. When the daemon is serving this project, approval links use its registered port. Use `--public-url` when reviewers need a URL other than the local server address.
## Optional Slack Channel
Slack can alert reviewers when an approval is waiting. Approval state still lives in the AgentUse session page.
The Slack channel message stays concise, and supporting approval details are posted in the message thread when the agent provides them. Those thread details can include summary, draft, artifact, context, and risk.
```yaml theme={"system"}
approval: true
channels:
slack:
events: [approval]
```
See [Channels](/guides/channels) for Slack setup, channel ids, events, and completion/failure channel messages.
## Reviewer Flow
Make each approval understandable without opening Draft or Context or reading "Why this request". Choose one primary review surface:
* **Actions:** use `prompt` + `changes`. Put the exact caption/body in `displayContent` when `content` is a command, attach the media in `media_urls`, and name the destination account/platform and timing in the action label. Material revisions belong in the visible prompt or action label, and critical consequences belong in `risk`.
* **Standalone deliverables:** first create and save the report, proposal, or other artifact using `tools__artifact_save` when available or another suitable creation tool. Wait for success, then call `await_human` with its returned `artifact_path` (or `artifact_paths` for several files). Use `artifact_url` for an existing hosted deliverable. Never invent paths or URLs. Artifacts appear in an expanded section; supported local formats and hosted media have inline previews, and hosted documents have a visible open link.
Omit `draft`, `summary`, and `context` by default. Existing payloads remain supported.
The session page supports these review fields:
* `prompt`: the reviewer-facing decision prompt
* `changes`: the exact actions taken on approval, one `{ label, content }` entry per discrete action. Each renders as a highlighted "On approval" box with a copy button and character count, so the reviewer skims the verbatim payload first. When `content` is a command, `displayContent` carries the human-facing body; for a thread or any multi-post submission, pass `displayContent` as a list of strings, one per post, and the card renders them as numbered posts. Add `media_urls` when an action carries an external image, video, or audio asset; supported media renders inline in the same action card for review
* `reference`: the original item the action responds to (`{ label, author, title, url, excerpt }`), such as the post being commented on or the message being replied to. On a wide screen it renders in a column beside the changes, so the reviewer reads original and response together; on a narrow one it stacks above them
* `options`: two or more choices for the reviewer, each with an `id`, `label`,
and optional `description` / `recommended`. The session page renders a
single-choice picker before the decision controls. On approval, the selected
id reaches the agent as `toolResult.choice`
* `summary`: optional background under "Why this request"; never the only place essential review information appears
* `draft`: legacy inline Markdown, retained for compatibility. Use actions or saved artifacts in new requests. When `changes` carries the verbatim payload, the draft renders collapsed as supporting detail
* `draft_url`: URL to a draft artifact
* `artifact_url`: URL to the primary review artifact, such as a PR, preview, document, or generated artifact
* `artifact_path` / `artifact_paths`: project-relative local files the session page can open in the artifact viewer. Images, HTML, and PDF artifacts render inline; MP4/WebM/MOV/M4V video and MP3/M4A/WAV/OGG audio use native players. Files are snapshotted at gate time so the reviewer approves immutable bytes
* `context`: background the other fields do not already carry (constraints, inputs used, process notes); agents are steered to omit it rather than repeat the reference, changes, or summary
* `risk`: known risks, unresolved questions, or reviewer attention areas
* Session logs before and after the decision
Review bodies support Markdown, including headings, emphasis, links, blockquotes,
numbered lists (`1.` or `1)`), bullet lists, tables, and fenced code. This includes
`changes[].displayContent`, individual thread posts, and `reference.excerpt`.
Preserve the exact submitted body and original quote, including any existing
Markdown. Copy buttons retain the source text; rendering does not change the
approved payload or executable command. Raw HTML is escaped.
### The original is mandatory on a response gate
When the gate approves a reply, comment, answer, or any other response to
something someone else wrote, `reference` is required and its `excerpt` must
carry the **complete verbatim original**, not a summary and not the first few
lines. The schema rejects three shapes that force the reviewer to leave the
card and open the source:
* a response gate with no `reference` at all (putting the original in `context`
prose does not count)
* a `reference` that carries an author, title, or `url` but no `excerpt`
* an `excerpt` with an explicit elision marker such as `[truncated]` or
`(full text at the link)`
A gate for a *fresh* post, email, or document is unaffected: it answers nothing,
so it has no original to quote.
Reviewer actions are fixed:
* `Approve`: resumes the agent with `status: "approve"`
* `Reject`: resumes the agent with `status: "reject"`
* `Comment`: resumes the agent with `status: "comment"` and the reviewer comment
`Comment` is the revise-and-re-gate path, not a failed selection. On a choice
gate, an actionable edit or direct replacement in the comment takes precedence
over the absence of a selected option. For example, `reply "very nice!"` means
to replace the proposed reply with `very nice!` and request approval again; it
is not ambiguous merely because it names no option. Only an explicit request to
cancel, abandon, or stop makes a comment terminal.
For a choice gate, AgentUse preselects the recommended option, or the first
option when none is recommended. The reviewer can change that selection before
approving. The result retains the normal approval status and adds the selected
option id:
```json theme={"system"}
{
"status": "approve",
"choice": "ship_tuesday"
}
```
Use stable machine-readable ids. Labels and descriptions may change without
breaking the agent logic that consumes `toolResult.choice`.
On reject, AgentUse passes the decision back to the agent instead of applying a
universal workflow state change. If the agent tracks drafts, queue items, or
tasks in a store, describe the rejected-state transition in the agent
instructions, such as "when rejected, mark the current draft item `rejected`"
or "when rejected with feedback, mark it `needs_revision`."
When Slack Socket Mode is configured, the approval details thread can also accept Approve, Reject, Comment, and normal thread replies. Without Socket Mode, reviewers open the session page link to decide.
When the agent receives a comment, it decides whether to revise, ask for approval again, or stop with a clear explanation.
After the run completes, the same session page becomes a lightweight continuation surface. Add a follow-up instruction in the **Resume session** box to resume the completed or errored session with its existing context. This matches Slack thread replies, but keeps the web session page as the source of truth for details and logs.
If an approval decision was submitted but the resumed run failed downstream, the session page may offer **Retry**. Retry reopens the latest resolved approval gate, preserves the original session token, and lets the reviewer submit the decision again. Use it only when it is safe to retry the downstream work; the UI warns about possible duplicate external side effects.
If a decision itself fails, the approval card says what failed, whether the decision was applied, and what to do next: **Reconnect** or **Connect** for a provider sign-in, **Retry** for a transient worker or provider failure, and nothing when the gate was already answered, changed, ended, or expired. Your typed comment is kept. Draft, revision, and change set pages show the same panel.
## Approval in delegated sub-agents
A leaf agent's approval gate behaves identically whether you run it directly or a `type: manager` agent delegates to it. You define `approval: true` once on the leaf, and the same human gate fires in both modes. Only the channel the request surfaces through changes.
```md title="reply-to-post.agentuse — the leaf, reused in both modes" theme={"system"}
---
model: anthropic:claude-sonnet-5
approval: true
---
Draft a reply to the given post in the brand voice, then publish it.
```
* **Run it directly** (`agentuse run reply-to-post.agentuse`) and you get the gate, as for any top-level agent.
* **Delegate it** from a manager and the *same* gate fires inside the sub-agent. The request surfaces **on the manager run's session page** (and the `/approvals` inbox, and Slack if configured), labeled with the originating leaf. Approve / reject / comment there: the decision resolves the leaf's gate, the leaf finishes, and the manager resumes automatically.
```md title="manager.agentuse — delegates to the same leaf, unchanged" theme={"system"}
---
type: manager
schedule: "0 9 * * *"
subagents:
- path: ./reply-to-post.agentuse
---
For each post worth replying to, delegate to reply-to-post.
```
This works for an interactive manager and for a scheduled/headless one: the run suspends durably and resumes when the decision arrives.
**Approve at the manager root.** The delegated leaf's own session page is view-only and links up to the manager run, where the decision is made. This keeps one canonical approval surface per run.
**v1 behavior and limits:**
* One approval at a time per manager run. To gate several items, have a single leaf loop and call the gate once per item (it re-suspends and re-surfaces at the root each time), rather than fanning out to many sub-agents that suspend simultaneously, concurrent multi-gate fan-out is not yet supported.
* The human always decides outward/irreversible actions (human relay). Automatic, classifier-based approval of low-risk calls is a separate, later option.
* Resolve a delegated gate from the manager's approval page, `/approvals` inbox, or Slack, not `agentuse sessions resume`, which handles only single-session gates.
## Configuration Fields
Approval config is intentionally small:
```yaml theme={"system"}
approval: true
```
or:
```yaml theme={"system"}
approval:
timeout: 24h
```
* `approval`: `true` or an object to enable the approval gate
* `approval.timeout`: optional suspension timeout, such as `30m`, `24h`, or `7d`. A bare number means seconds.
* `tools.bash.gated`: bash command patterns that run only after human approval, enforced by a per-action lease. Declaring it implies the approval gate. See [Gated commands](#gated-commands-mechanical-enforcement).
Channel config is separate:
```yaml theme={"system"}
channels:
slack:
events: [approval]
channel_id: C0123456789
```
* `channels`: optional external collaboration channels, such as `channels: [slack]`
* `channels.slack.events`: events for Slack. Approval gates use `approval`; terminal run events are documented in [Channels](/guides/channels).
* `channels.slack.channel_id`: Slack channel id. If omitted, AgentUse uses `SLACK_APPROVAL_CHANNEL`.
* `channels.slack.enabled`: optional switch for temporarily disabling Slack
## Auth and the session token
Authentication follows the deployment invariant:
* **Local bind** (`127.0.0.1` / `localhost` / `::1`): no API key, no token. View and approve are fully open. A keyless daemon only answers requests addressed to `localhost`, `127.0.0.1`, `[::1]`, `*.localhost`, or the host of its [public URL](/reference/configuration-files); anything else gets `403 HOST_NOT_ALLOWED`.
* **Exposed host**: `serve` refuses to start without `AGENTUSE_API_KEY` (use `--no-auth` to bypass, dangerous). The API key (`Authorization: Bearer`) authorizes everything.
Because a `Bearer` header is not clickable from a Slack message or an email, each session also has a **session token**: a stateless, per-session value that stands in for the API key on that one session's page.
```text theme={"system"}
sessionToken = base64url( HMAC-SHA256(key = AGENTUSE_API_KEY, msg = sessionId) )
```
One token grants both **view** and **approve** for its session, and the same value works for every gate in that session. It is unguessable without the API key and is scoped to a single session (a token for session A never authorizes session B). On localhost there is no API key, so there is no token and links omit it. `await_human` mints this token when it builds the reviewer link, so Slack/email links are clickable without an API-key login.
The token covers viewing and deciding only. It cannot continue a run with a new prompt, add or discard learnings, reach the parent session, or open project files other than that session's gate artifacts, snapshots, and saved deliverables. Those need the API key, or a local keyless daemon.
While a run is suspended, anyone with its session link can approve it. A completed run has no pending gate, so a shared completed-log link cannot approve anything. The view + approve conflation only matters during the approval window.
## Experimental session / approval API
The API is experimental and mirrors the web session page contract. Use it to build custom review UIs or integrations.
JSON endpoints live under the `/api/*` prefix and are always API-key gated on an exposed host. The HTML session page and its action subroutes carry their own capability auth (session token / API key / local), so a tokenized link works without a `Bearer` header.
List sessions as JSON (filter by `agent`, `trigger`, or time window with `days`):
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions?trigger=scheduled&days=7" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
Fetch one session (summary + run-log entries):
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions/session_abc123" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
Poll a session's live status (session token works in place of a header):
```bash theme={"system"}
curl "http://127.0.0.1:12233/sessions/session_abc123/status?token=$sessionToken"
```
Submit a decision. Authorize with the session token (`?token=`) or a `Bearer`
header; the current pending gate is resolved server-side, so you do not pass a
gate token:
```bash theme={"system"}
curl -X POST "http://127.0.0.1:12233/sessions/session_abc123/decision?token=$sessionToken" \
-H "Content-Type: application/json" \
-d '{ "status": "approve", "comment": "Looks good" }'
```
When a decision fails, the open-gate payload carries `actionFailure: { kind, provider?, retryable }` (plus `action`, `code`, and `message`), which the approval card uses to pick Reconnect, Retry, or nothing.
The decision endpoint returns immediately while the suspended session resumes in the background:
```json theme={"system"}
{
"sessionId": "session_abc123",
"status": "resuming"
}
```
Continue a completed or errored session (operator only; a session token is refused with `403 OPERATOR_REQUIRED`):
```bash theme={"system"}
curl -X POST "http://127.0.0.1:12233/sessions/session_abc123/continue" \
-H "Authorization: Bearer $AGENTUSE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "Please revise the CTA and run the smoke test again" }'
```
The continuation endpoint also returns immediately while AgentUse starts the follow-up run:
```json theme={"system"}
{
"sessionId": "session_abc123",
"status": "continuing"
}
```
Reopen the latest resolved approval gate on an ended session:
```bash theme={"system"}
curl -X POST "http://127.0.0.1:12233/sessions/session_abc123/reopen?token=$sessionToken" \
-H "Content-Type: application/json" \
-d '{}'
```
The reopen endpoint returns the session to `suspended` so the normal decision flow can run again:
```json theme={"system"}
{
"success": true,
"sessionId": "session_abc123",
"status": "suspended"
}
```
**Legacy approval routes.** `GET /approvals/:id` now redirects to `/sessions/:id`, and the older `/approvals` JSON list plus the `/api/approvals/:id/{status,decision,continue}` action endpoints remain available for backward compatibility. Those legacy action endpoints still take a gate `resumeToken` in the body. In-flight Slack links from before the upgrade keep working: the session page also accepts a valid gate `resumeToken` as a credential until those approvals expire. The legacy `/api/approvals/:id/continue` endpoint is operator-only as well. Prefer the `/sessions` routes and the session token for new integrations.
## Local Testing
For development or manual testing, you can resume a suspended session from the CLI:
```bash theme={"system"}
agentuse sessions resume session_abc123 --approve
```
You can also reject or comment without writing JSON:
```bash theme={"system"}
agentuse sessions resume session_abc123 --reject "Not ready"
agentuse sessions resume session_abc123 --comment "Shorten this and add pricing"
```
Prefer the `/approvals` UI for normal review, Slack for reviewer alerts, the Approval API for custom review surfaces, and `agentuse sessions resume` for local testing.
### Testing gate flows unattended
Resuming by hand is fine for one gate. To check that each branch behaves, let `agentuse test` play the reviewer deterministically:
```bash theme={"system"}
agentuse test my-agent.agentuse --approval approve
agentuse test my-agent.agentuse --approval reject
agentuse test my-agent.agentuse --approval comment:"tighten the subject line"
```
The run finishes with no human involved, and an approval grants the gated-command lease exactly like a real reviewer, so `tools.bash.gated` flows complete end to end without executing anything irreversible. See [Testing Agents](/guides/testing-agents).
# Channels
Source: https://docs.agentuse.io/guides/channels
Connect AgentUse lifecycle events such as approval, completion, and failure to Slack
Channel event names and the `channels` configuration contract are
experimental and may change without migration as AgentUse adds destinations.
Channels connect AgentUse lifecycle events to external collaboration surfaces. In the current release, Slack is the implemented channel.
Use channels when a person should know that an agent needs review, finished successfully, or failed, or when Slack thread replies should continue a run.
## Basic Slack Setup
Add Slack to the agent frontmatter:
```yaml theme={"system"}
channels: [slack]
```
For explicit event selection:
```yaml theme={"system"}
channels:
slack:
events: [completion, failure]
channel_id: C0123456789
```
Set a Slack bot token and default channel:
```bash theme={"system"}
export SLACK_BOT_TOKEN="xoxb-..."
export SLACK_APPROVAL_CHANNEL="C0123456789"
```
To get a Slack bot token:
1. Go to [api.slack.com/apps](https://api.slack.com/apps) and create or open a Slack app.
2. Open **OAuth & Permissions**.
3. Add the bot token scope `chat:write`.
4. Click **Install to Workspace** or **Reinstall to Workspace**.
5. Copy the **Bot User OAuth Token**. It starts with `xoxb-`.
Optional: add `assistant:write` if you want Slack Assistant thread status while a live run is active.
Approval channel threads can also accept decisions. For Approve/Reject buttons and comment-by-thread-reply, configure Socket Mode:
```bash theme={"system"}
export SLACK_APP_TOKEN="xapp-..."
```
The app-level token needs `connections:write`. To resume from normal thread replies, enable Slack event subscriptions for `message.channels` and, if you use private channels, `message.groups`; add `channels:history` and/or `groups:history` bot scopes as needed.
To get a channel id:
1. Open the channel in Slack.
2. Click the channel name.
3. Copy the channel id from the channel details panel. It starts with `C...` for public channels or `G...` for private channels.
You can also copy a channel link and use the `C...` or `G...` value from the URL.
Invite the bot to the target channel before sending channel messages. For private channels, this is required.
## Slack Config
V1 supports one Slack channel per agent.
```yaml theme={"system"}
channels:
slack:
events: [approval, completion, failure]
channel_id: C0123456789
```
Fields:
* `channels.slack`: `true` or an object to enable Slack
* `channels.slack.enabled`: set to `false` to temporarily disable Slack
* `channels.slack.events`: event or list of events
* `channels.slack.channel_id`: Slack channel id for this agent
Slack can be written in any of these forms:
```yaml theme={"system"}
channels: [slack]
```
```yaml theme={"system"}
channels:
slack: true
```
```yaml theme={"system"}
channels:
slack:
events: [approval]
channel_id: C0123456789
```
If `channel_id` is omitted, AgentUse uses `SLACK_APPROVAL_CHANNEL`.
## Events
Supported event names:
* `approval`: the agent created an approval request and is waiting for review
* `completion`: the agent finished successfully
* `failure`: the agent ended with an execution error
A run whose blocker is a person (waiting on an approval or review, or rejected by one) does not fire `failure`. Its live run card settles as **run incomplete** with the agent's reason.
Use `completion`, not `complete` or `completed`.
If `events` is omitted, AgentUse enables all supported events.
`completion` and `failure` are terminal run events. A Slack channel that listens for `approval`, or for both `completion` and `failure`, posts a run-start card immediately and updates the same card when the run completes, fails, or waits for approval. Single-outcome channels such as `events: [failure]` stay terminal-only so they do not leave stale running messages.
## Slack Messages
Slack uses one concise channel message as the status card and puts approval details in that message's thread.
Approval channel messages include:
* Channel card with prompt, session/project metadata, status, and a Review approval button
* Thread details with summary, draft, artifact, context, and risk when the agent provides them
* Thread actions for Approve, Reject, and Comment when Socket Mode interactivity is enabled
* Plain thread replies become `comment` decisions when Socket Mode message events are enabled
The AgentUse session page (`/sessions/`) remains the source of truth for review state.
Completion channel messages include:
* Channel card with agent name, session id, status, and duration
* Thread details with the final answer, tool call count, and token count when available
Failure channel messages include:
* Channel card with agent name, session id, status, and duration when available
* Thread details with the error message and run metadata
When Slack Socket Mode message events are enabled, a reviewer can reply in a completed or failed run channel thread to continue from that session with the reply as the new instruction.
For live run cards, AgentUse also tries Slack Assistant thread status while the run is active. This is best effort; Slack may ignore it when the app does not have Assistant support.
## Approval Gates
Approval Gates use channels only to alert reviewers. Configure the approval policy separately:
```yaml theme={"system"}
approval: true
channels:
slack:
events: [approval]
```
See [Approval Gates](/guides/approval-gates) for the approval dashboard, reviewer flow, and Approval API.
# CI/CD
Source: https://docs.agentuse.io/guides/cicd
Configure AgentUse agents to run in GitHub Actions for automated PR reviews, comment responses, and custom workflows.
This guide uses [agentuse/pr-review-agent](https://github.com/agentuse/pr-review-agent) as a comprehensive example. You can copy its workflows and agents directly to your project.
## Overview
GitHub Actions can run AgentUse agents in response to repository events:
* **PR Reviews**: Automatic code review when PRs are opened/updated
* **Comment Replies**: Respond to @mentions in PR/issue comments
* **Custom Workflows**: Manual or scheduled agent runs
## Quick Start
### 1. Copy Workflow Files
From the [agentuse-pr-agents](https://github.com/agentuse/agentuse-pr-agents) repository:
```bash theme={"system"}
# Copy workflows and agents to your project
cp -r .github/agents .github/workflows your-project/.github/
```
This gives you:
```
.github/
├── workflows/
│ ├── agentuse-code-review.yml # PR review automation
│ └── agentuse-comment-reply.yml # @mention responses
└── agents/
├── code-review.agentuse # Review agent prompt
└── comment-reply.agentuse # Reply agent prompt
```
### 2. Configure API Keys
Add ONE of these secrets to your repository (**Settings → Secrets → Actions**):
| Secret Name | Provider | Get From | Best For |
| - | - | - | - |
| `ANTHROPIC_API_KEY` | Anthropic | [console.anthropic.com](https://console.anthropic.com) | Pay-per-use |
| `OPENAI_API_KEY` | OpenAI | [platform.openai.com](https://platform.openai.com) | GPT models |
| `OPENROUTER_API_KEY` | OpenRouter | [openrouter.ai](https://openrouter.ai) | Multi-provider |
| `OPENCODE_GO_API_KEY` | OpenCode Go | [opencode.ai/auth](https://opencode.ai/auth) | Open coding models |
| `CLAUDE_CODE_OAUTH_TOKEN` | Claude Pro/Max | `npx agentuse auth setup-github` | Subscription users; provider plugin required |
For Claude Pro/Max users, install the Claude Code subscription provider plugin in the project or runner image, then run `npx agentuse auth setup-github` in your project directory. The command writes the token secret to GitHub; the token alone does not install or activate its transport.
### 3. Done
Open a PR to trigger automatic review, or mention `@agentuse` in any comment.
## Workflow Configuration
### PR Code Review Workflow
**File**: `.github/workflows/agentuse-code-review.yml`
#### Key Configuration
```yaml theme={"system"}
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to review'
required: true
type: number
permissions:
contents: read
pull-requests: write
concurrency:
group: pr-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
```
#### Environment Variables
The workflow sets these variables for the agent:
| Variable | Description |
| - | - |
| `GITHUB_REPOSITORY` | Repo name (e.g., `user/repo`) |
| `PR_NUMBER` | Pull request number |
| `BASE_REF` | Target branch (e.g., `main`) |
| `HEAD_REF` | Source branch |
| `GH_TOKEN` | GitHub token for API access |
### Comment Reply Workflow
**File**: `.github/workflows/agentuse-comment-reply.yml`
#### Key Configuration
```yaml theme={"system"}
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '@agentuse')
```
#### Context Variables
| Variable | Description |
| - | - |
| `COMMENT_ID` | Comment ID for threading |
| `COMMENT_AUTHOR` | Who mentioned the bot |
| `COMMENT_BODY` | Full comment text |
## Agent File Configuration
### Structure
Agent files use YAML frontmatter + markdown:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
maxSteps: 50
tools:
bash:
commands:
- "gh *"
- "git *"
filesystem:
- path: "${root}"
permissions: [read]
---
# Your Agent Instructions
Instructions here in markdown...
```
### Model Selection
Override the default model in three ways:
**1. Agent file** (recommended for consistency):
```yaml theme={"system"}
model: anthropic:claude-opus-5
```
**2. Workflow dispatch input** (one-time override):
```yaml theme={"system"}
workflow_dispatch:
inputs:
model:
description: 'Model override'
type: string
```
**3. Environment variable** (all runs):
```yaml theme={"system"}
env:
MODEL: openai:gpt-5.6
```
Priority: Dispatch input → Env var → Agent file
### Tool Permissions
Limit what the agent can do:
```yaml theme={"system"}
tools:
bash:
commands:
- "gh *" # GitHub CLI only
- "git log *" # Limited git access
filesystem:
- path: "src/**" # Read source files only
permissions: [read]
```
### Timeout & Step Limits
```yaml theme={"system"}
maxSteps: 50 # Maximum agent steps
```
```bash theme={"system"}
# In workflow
npx agentuse run agent.agentuse --timeout 300 # 5 minute timeout
```
## Advanced Configuration
### Filter PRs by Path
```yaml theme={"system"}
on:
pull_request:
paths:
- 'src/**'
- '!**/*.test.ts'
```
### Different Models per Task
```yaml theme={"system"}
# .github/agents/quick-review.agentuse
model: anthropic:claude-haiku-4-5
maxSteps: 20
```
### Skip Draft PRs
```yaml theme={"system"}
jobs:
review:
if: github.event.pull_request.draft == false
```
### Monorepo: Pass Affected Packages
Set environment variable in workflow:
```yaml theme={"system"}
env:
AFFECTED_PACKAGES: ${{ steps.detect.outputs.packages }}
```
Agent reads it at runtime:
````markdown theme={"system"}
## Step 1: Check Affected Packages
Run this command to see which packages changed:
\```bash
echo $AFFECTED_PACKAGES
\```
Focus your review on these packages only.
````
### Custom Review Standards
Edit `.github/agents/code-review.agentuse`:
```markdown theme={"system"}
## Security Checks
- No hardcoded secrets
- Input validation on endpoints
## Performance
- No N+1 queries
- Pagination on large lists
```
## Debugging
Enable debug mode in workflow:
```yaml theme={"system"}
env:
AGENTUSE_DEBUG: true
```
Common issues:
| Issue | Solution |
| - | - |
| Agent times out | Increase timeout: `--timeout 600`, reduce maxSteps, use faster model |
| Review not posting | Check `pull-requests: write` permission, verify API key |
| Wrong files reviewed | Check path filters, verify filesystem permissions |
Before pushing a workflow change, run the agent locally with [`agentuse test`](/guides/testing-agents): it exercises the whole run without posting comments or touching the repository.
## Security
Limit agent access in CI:
```yaml theme={"system"}
tools:
bash:
commands:
- "gh pr *" # Only PR commands, not repo admin
filesystem:
- path: "src/**" # Don't expose .env, secrets/
permissions: [read] # Never [write] in CI
```
## Cost Optimization
### Use Cheaper Models
```yaml theme={"system"}
# For simple PRs
model: anthropic:claude-haiku-4-5 # ~$0.01/review
# For complex PRs
model: anthropic:claude-sonnet-5 # ~$0.05/review
```
### Reduce Token Usage
```yaml theme={"system"}
maxSteps: 20 # Limit agent execution
```
In agent prompt:
```markdown theme={"system"}
Focus only on changed files. Ignore tests unless broken.
Provide concise summaries (2-3 sentences max per section).
```
### Skip Low-Value PRs
```yaml theme={"system"}
if: |
github.event.pull_request.draft == false &&
github.event.pull_request.additions > 10
```
## Reference
Common bash commands in agents:
```bash theme={"system"}
# Get PR metadata
gh pr view $PR_NUMBER --json title,body,files
# Get diff
gh pr diff $PR_NUMBER
# Post comment
gh pr comment $PR_NUMBER --body "Review complete"
```
## Next Steps
* **Customize agents**: Edit `.github/agents/*.agentuse` to match your workflow
* **Add more workflows**: Create agents for deployment, testing, documentation
* **Share across repos**: Use organization-level secrets and reusable workflows
* See [Agent Design Patterns](/guides/agent-design-patterns) for advanced prompt engineering
# Coding agent integrations
Source: https://docs.agentuse.io/guides/coding-agent-integrations
# Coding-agent integrations
Use AgentUse from Codex, Claude Code, or Pi to turn a workflow in your current
conversation into a reusable `.agentuse` file. The integration helps define the
agent, prepare its runtime, and validate it before its first real run.
## Install
Install the repository skill with the cross-host Agent Skills installer:
```bash theme={"system"}
npx skills add agentuse/agentuse
```
This is the supported installation path for Codex, Claude Code, Cursor, Gemini
CLI, GitHub Copilot, Goose, OpenCode, Windsurf, and other compatible hosts.
New GitHub Releases do not contain separate coding-assistant packages.
Start a new conversation after installation, then ask your assistant:
```text theme={"system"}
Use AgentUse to turn the workflow we just completed into a reusable agent.
```
The installed discovery skill loads the `automate`, `core`, `creator`, and
`tester` guidance from the installed AgentUse CLI. This keeps the authoring
workflow aligned with the CLI version that will validate and run the resulting
agent.
The Pi-specific adapter is currently available to contributors from a source
checkout. Run `bun run integrations:build`, install
`./dist/integrations/pi` with Pi, and start a new session before using
`/automate`.
## Validate and run the resulting agent
The assistant loads current AgentUse guidance from the installed `agentuse`
command. Running and validating the file requires the
[AgentUse CLI](/installation) and a configured model provider.
Review the generated source and setup requirements, then validate and test it:
```bash theme={"system"}
agentuse doctor my-agent.agentuse
agentuse test workflow my-agent.agentuse
```
See [testing agents](/guides/testing-agents) for test scope and limitations.
Review the test output before a real run or enabling a schedule.
## Updates and local development
Run `npx skills add agentuse/agentuse` again when you want the latest discovery
skill. Its workflow guidance is version-matched at runtime by the AgentUse CLI.
Contributors can run `bun run integrations:build` in the AgentUse repository.
The generated local-development marketplaces use `agentuse-development`; their
installation commands are in the repository's `integrations` READMEs.
# Context Management
Source: https://docs.agentuse.io/guides/context-management
How AgentUse manages conversation context efficiently
## Overview
AgentUse automatically manages conversation context to keep your agents running efficiently within token limits. This ensures long-running agents don't hit token limits while preserving important information.
## Automatic Compaction
When conversations approach token limits, AgentUse automatically:
1. Detects when context usage exceeds the threshold
2. Compacts older messages into a concise summary
3. Preserves recent messages for continuity
4. Continues the conversation seamlessly
Compaction happens transparently - your agent continues working without interruption.
## How It Works
### Token Tracking
AgentUse tracks token usage throughout the conversation and compacts when approaching limits. The system uses character-based estimation (approximately 4 characters per token) and updates with actual usage data from the AI models.
### Compaction Strategy
AgentUse uses a **summarization-based** approach:
* Older messages are summarized using the same model as the agent
* Recent messages are preserved intact for continuity
* The summary captures key decisions, tool results, and progress
* System prompts and tool definitions are always preserved
## Configuration
### Environment Variables
Control context management globally using environment variables:
```bash theme={"system"}
# Enable/disable context compaction (default: enabled)
CONTEXT_COMPACTION=true
# Set compaction threshold as percentage (default: 0.7 = 70%)
COMPACTION_THRESHOLD=0.8
# Number of recent messages to preserve (default: 3)
COMPACTION_KEEP_RECENT=5
# Compact at approval gates once active context reaches this size (default: 64000)
APPROVAL_COMPACTION_MIN_TOKENS=64000
# Compact between LLM steps after tool calls once active context reaches this size (default: 64000)
STEP_COMPACTION_MIN_TOKENS=64000
# Maximum agent steps before stopping (default: 1000)
MAX_STEPS=2000
```
## What Gets Preserved
### Always Preserved
* System prompts
* Recent messages (last 3 by default, configurable)
* Tool definitions remain available
### What Gets Compacted
* Older conversation history
* Previous tool calls and results
* Assistant responses from earlier in the conversation
The compaction creates a summary that preserves:
* Key decisions and outcomes
* Important tool results and errors
* Current state and progress
* Critical information needed for continuation
## Compaction Details
### Compaction Process
When compaction is triggered:
1. Older messages are separated from recent ones
2. A summarization request is sent to the same model
3. The summary is created with a specialized system prompt
4. Recent messages are kept intact for continuity
5. The conversation continues with the compacted context
### Compaction Prompt
The system uses this prompt for summarization:
```
You are a conversation summarizer. Summarize the following agent context concisely, preserving:
1. Key decisions and outcomes
2. Important tool results and errors
3. Current state and progress
4. Any critical information needed for continuation
Be concise but comprehensive.
```
## Monitoring
### Token Usage
AgentUse displays token usage at the end of each run:
```
Tokens used: 12,450
```
For agents with sub-agents:
```
Tokens used: 18,750 (main: 12,450, sub-agents: 6,300)
```
### Compaction Events
When compaction occurs, you'll see:
```
Context approaching limit (85% used). Compacting agent context...
Context compacted successfully. Continuing...
```
## Context Limits by Model
AgentUse automatically detects context limits for different models:
* **Anthropic models**: Retrieved from models.dev API
* **OpenAI models**: Retrieved from models.dev API
* **Unknown models**: Default to 32,000 tokens (conservative)
The system updates context limits dynamically based on the latest model information.
## Performance Considerations
Compaction requires an additional API call to summarize context, adding 1-3 seconds to processing time
Compaction itself uses tokens (up to 2000 for the summary), but saves significantly more in long conversations
Summaries preserve key information but some nuance may be lost. Recent messages remain fully intact
## Best Practices
### 1. Set Appropriate Thresholds
```bash theme={"system"}
# Conservative (compact early, better context preservation)
COMPACTION_THRESHOLD=0.6
# Aggressive (compact late, more context before compaction)
COMPACTION_THRESHOLD=0.9
# Balanced (recommended default)
COMPACTION_THRESHOLD=0.7
```
### 2. Adjust Recent Messages
```bash theme={"system"}
# Keep more recent messages (better continuity, more tokens used)
COMPACTION_KEEP_RECENT=5
# Keep fewer recent messages (more aggressive compaction)
COMPACTION_KEEP_RECENT=2
```
### 3. Tune Approval-Boundary Compaction
```bash theme={"system"}
# Compact earlier at human approval pauses to reduce repeated input spend
APPROVAL_COMPACTION_MIN_TOKENS=32000
# Disable approval-boundary compaction but keep model-limit compaction
APPROVAL_COMPACTION_MIN_TOKENS=0
```
Approval-boundary compaction is useful for long runs with human review gates.
It can compact before the model window is close to full because the goal is to
avoid resending a large active context after the session resumes.
### 4. Tune Step-Boundary Compaction
```bash theme={"system"}
# Compact less often during autonomous tool loops
STEP_COMPACTION_MIN_TOKENS=128000
# Disable split-turn step compaction but keep approval and model-limit compaction
STEP_COMPACTION_MIN_TOKENS=0
```
Step-boundary compaction runs after the agent has already made at least one
tool call. It preserves the initial prompt, then summarizes older context before
later model calls in long single-turn runs.
### 5. Disable if Not Needed
```bash theme={"system"}
# Disable for short conversations
CONTEXT_COMPACTION=false
```
### 6. Cap and Reduce Tool Output
Every tool result is re-sent to the model on each subsequent step, so a single large output (a big diff, a verbose log, a huge file read) is one of the biggest drivers of input-token usage, often before compaction ever triggers. The most effective fix is to not generate the bloat in the first place, for example `git diff --stat` instead of a full `git diff` of high-churn files.
As a safety net, direct JSON and text results over 10KB become a reusable handle with one partial value in `preview` and a compact `omitted` map showing what was left out at each jq-style path. The read-only `results` tool can return up to 20KB of selected text matches or JSON fields without repeating the preview or creating another handle. Provider-native and binary results using native model-output conversion remain on their direct delivery path. Bash separately retains a head + tail preview up to 30KB and saves a complete session artifact when its stream is larger. `read_file` defaults to 2000 lines. Tune these with the [Tool Output environment variables](/reference/environment-variables#tool-output):
```bash theme={"system"}
# Allow larger bash output before truncation
AGENTUSE_TOOL_MAX_OUTPUT_BYTES=61440
# Allow a larger direct result to remain inline
AGENTUSE_TOOL_INLINE_RESULT_BYTES=16384
# Allow larger intentional result queries
AGENTUSE_RESULT_QUERY_BYTES=32768
# Return more lines per read_file call
AGENTUSE_TOOL_MAX_LINES=5000
```
## Technical Details
### Token Estimation
* Uses character-based estimation: \~4 characters per token
* Updates with actual token usage from AI models
* Tracks both input and output tokens
### Model Integration
* Context limits are fetched from models.dev API
* Falls back to conservative 32,000 token limit for unknown models
* Caches model information for 24 hours
### Error Handling
* If compaction fails, creates a fallback summary
* Continues execution even if compaction encounters errors
* Logs compaction failures for debugging
## Troubleshooting
* Increase `COMPACTION_KEEP_RECENT` for more preserved messages
* Lower `COMPACTION_THRESHOLD` to compact earlier with more context
* The same model is used for summarization, so quality should be consistent
* Lower `COMPACTION_THRESHOLD` to compact earlier
* Reduce `COMPACTION_KEEP_RECENT` for more aggressive compaction
* Consider the model's actual context limit vs your usage
* Check that `CONTEXT_COMPACTION` is not set to 'false'
* Verify the model supports the context limits being used
* Check logs for compaction errors
## Example: Long-Running Agent
```yaml theme={"system"}
---
name: data-analyzer
model: anthropic:claude-sonnet-5
---
You analyze large datasets over extended periods.
Process data systematically and maintain detailed progress tracking.
```
```bash theme={"system"}
# Configure for long-running analysis
export MAX_STEPS=2000
export COMPACTION_THRESHOLD=0.8
export COMPACTION_KEEP_RECENT=5
# Run the agent
agentuse run data-analyzer.agentuse
```
The agent will automatically:
* Track token usage throughout the analysis
* Compact context when approaching 80% of the model's limit
* Preserve the last 5 messages for continuity
* Continue analysis without interruption
## Next Steps
Build efficient agents
Configuration options
# Creating Agents
Source: https://docs.agentuse.io/guides/creating-agents
Define AI agents in markdown and run on cron, CI/CD, or serverless
## Agent File Format
AgentUse agents are markdown files with a `.agentuse` extension. They consist of:
1. **Frontmatter** - YAML configuration
2. **Agent Prompt** - Agent instructions
## Basic Structure
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
description: "General-purpose AI assistant for various tasks"
---
You are a helpful assistant.
## Task
Help the user with their request.
```
The agent name is automatically derived from the filename. You don't need to specify it in the frontmatter.
## Frontmatter Configuration
### Required Field
The AI model to use. Format: `provider:model-name`
Examples:
* `anthropic:claude-opus-5`
* `anthropic:claude-sonnet-5`
* `anthropic:claude-haiku-4-5`
* `openai:gpt-5.6`
* `openai:gpt-5.4-mini`
* `openai:gpt-5.4-nano`
* `openrouter:z-ai/glm-5.3`
You can also specify environment variable suffixes:
* `anthropic:claude-sonnet-5:dev` (uses ANTHROPIC\_API\_KEY\_DEV)
* `openai:gpt-5.6:prod` (uses OPENAI\_API\_KEY\_PROD)
* `openai:gpt-5.6:OPENAI_API_KEY_PERSONAL` (uses specific env var)
### Optional Fields
A concise description of the agent's purpose.
This appears in:
* Tool descriptions when used as a sub-agent
* CLI output when running the agent
* Plugin events for logging
Best practices:
* Keep under 80-120 characters
* Be action-oriented
* Focus on primary capability
MCP server configurations. Each server can have:
* `command` + `args`: For stdio-based servers
* `url`: For HTTP-based servers
* `env`: Environment variables for the server
* `requiredEnvVars`: Required environment variables (fail if missing)
* `allowedEnvVars`: Optional environment variables to pass
* `allowedTools`: Array of tool names/patterns to load; every other tool stays off
* `disallowedTools`: Array of tool names/patterns to exclude
* `auth`: Authentication for HTTP servers
* `headers`: HTTP headers for HTTP servers
List of sub-agent configurations. Each sub-agent can have:
* `path`: Path to the agent file (required)
* `name`: Optional custom name for the sub-agent
* `maxSteps`: Optional maximum number of steps the sub-agent can take
## MCP Server Integration
Connect to Model Context Protocol servers for external tools and data sources:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
filesystem:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
---
```
See the complete reference for stdio servers, HTTP servers, environment variables, authentication, and tool restrictions.
## Using Sub-Agents
Agents can delegate to other agents. All sub-agent paths are resolved relative to the parent agent file's directory:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: "Coordinator agent that manages research and writing tasks"
subagents:
- path: ./research-agent.agentuse # Same directory as parent
name: "research_specialist" # Optional custom name
maxSteps: 100 # Optional: limit sub-agent steps
- path: ../utils/writer-agent.agentuse # Parent directory
- path: ./team/editor.agentuse # Subdirectory
---
You coordinate between research and writing agents.
## Task
When asked to create content:
1. Use the research agent to gather information
2. Use the writer agent to create the content
```
Sub-agents can be local files or HTTPS URLs. Remote agents must end with `.agentuse` extension.
## Environment Variables
Environment variables configure API keys, behavior settings, and MCP server credentials.
See the complete reference for API keys, behavior control, MCP server configuration, and security best practices.
## Runtime Customization
You can append additional prompts when running agents without modifying the agent file:
```bash theme={"system"}
# Run with base instructions
agentuse run code-review.agentuse
# Add specific focus areas
agentuse run code-review.agentuse "focus on security and performance"
# Customize behavior temporarily
agentuse run assistant.agentuse "respond in a formal tone"
# Provide additional context
agentuse run analyzer.agentuse "use production database settings"
```
This is useful for:
* Testing different approaches without editing files
* Providing context-specific instructions
* Reusing agents with slight variations
* Quick experimentation
## Examples
For a comprehensive collection of agent examples, including data analysis, code review, API integration, and more, visit the [AgentUse Templates](https://github.com/agentuse/agentuse/tree/main/templates/agents).
## Project Structure and Path Resolution
### Project Root Detection
AgentUse automatically detects your project root by searching upward for `.git/`, `.agentuse/`, or `package.json`.
### Recommended Project Structure
```
my-agent-project/
├── .env # Project-wide environment variables
├── .agentuse/
│ └── plugins/ # Custom plugins
│ └── logger.js
├── agents/
│ ├── main.agentuse # Main orchestrator
│ ├── research/
│ │ ├── web.agentuse
│ │ └── docs.agentuse
│ └── processing/
│ ├── analyzer.agentuse
│ └── formatter.agentuse
├── utils/
│ ├── helper.agentuse
│ └── validator.agentuse
└── tools/
└── custom-mcp-server # Custom MCP server executable
```
### Path Resolution
All paths (subagents, MCP server commands) are resolved relative to the **agent file's directory**, ensuring portability.
See [Agent Syntax - Subagents](/reference/agent-syntax#subagents) for complete path resolution examples.
### Benefits of This Structure
1. **Portability**: Share entire agent projects without breaking paths
2. **Organization**: Clear separation of concerns
3. **Reusability**: Utils and helpers can be shared across agents
4. **Version Control**: Everything in one repository
5. **Environment Management**: Single `.env` file for all agents
## Validate Before You Run It for Real
A new agent has two things worth checking before it touches anything that matters.
`agentuse doctor` checks the configuration: skills that don't exist, skills with no grants, commands the agent's own instructions mention but that it was never granted, and what the whole prompt costs per model request.
```bash theme={"system"}
agentuse doctor my-agent.agentuse
```
`agentuse test` checks the behaviour. It runs the agent end to end in mock mode: side effects are fabricated rather than executed, approval gates resolve automatically so the run finishes unattended, and stores are isolated from your real data.
```bash theme={"system"}
agentuse test my-agent.agentuse
```
The full edit-test-inspect loop, mock scope, approval branches, and what mock mode does and does not prove.
## Next Steps
Learn about delegating tasks to other agents
Best practices and patterns for building agents
See more agent examples
# Learning
Source: https://docs.agentuse.io/guides/learning
Capture what reviewers teach an agent, vet it, and apply the best of it in future runs
The `learning` configuration, capture behavior, and corrections-file format
are experimental and may change without migration. Discuss feedback in
[GitHub Discussions](https://github.com/agentuse/agentuse/discussions).
## What is Learning?
Learning lets reviewers deliberately teach an agent from real work. Leave a
comment at review time and check **Learn from this comment** when the feedback
should help in similar future situations. An unchecked comment revises the
current run only.
AgentUse turns checked feedback into concise, appropriately scoped guidance,
stores it in a readable markdown file, and applies it to later runs when
relevant. A learning is durable guidance, not an unconditional rule: the current
task and the agent's authored instructions still take precedence.
That deliberate human choice is the default. Automatic observation of a run is
advanced capability and remains available through explicit capture channels,
but it is never enabled merely by writing `learning: true`.
Everything a channel produces then passes a **vet** against the agent's complete
instructions before it can reach a future run, and everything that reaches a
future run is stamped with the version of those instructions it was checked
against.
## Quick Start
A single switch applies deliberate human learnings on future runs:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
approval: true # exposes review comments and the Learn checkbox
learning: true # apply checked feedback on similar future runs
---
# Blog Writer
Write short productivity blog posts.
## Guidelines
- Start with a relatable hook
- Include 3 actionable tips
```
During review, write the correction and check **Learn from this comment**. The
same operation is available as `--remember` in the CLI. AgentUse grounds the
comment in the work being reviewed, vets it against the agent's instructions,
and stores it. Unchecked comments are never added to durable memory.
`learning: true` is sugar for `{ capture: true, apply: true }`: it applies
explicitly saved human learnings, while automatic observation remains off.
Learnings accumulate in a
learnings file inside the AgentUse state directory, not in your repository.
`agentuse learnings ./blog-writer.agentuse --path` prints where; see
[Storage](#storage).
`capture: true` used to mean free-form auto-capture. As of v0.19.0 it enables
no automatic observation channels. Human feedback is saved through the Learn
checkbox, `--remember`, or manual add. See
[Upgrading an existing agent](#upgrading-an-existing-agent).
## Store Without Applying
To collect explicitly selected human learnings without putting them into future
prompts yet:
```yaml theme={"system"}
learning:
capture: true
apply: false # accumulate for manual review, never auto-inject
```
The Learn checkbox and `--remember` still save guidance. `apply: false` only
keeps it out of future prompts until you turn application back on.
## Advanced: Automatic Capture Channels
Most agents should stop at `learning: true`. Use capture channels only when you
also want AgentUse to learn without a reviewer checking Learn on a comment.
```yaml theme={"system"}
learning:
capture:
addons: [tool-errors] # typed, structurally-verified channels
custom: | # scoped free-form capture, built-in evaluator
Only note selector changes.
# agent: ./capture.agentuse # instead of custom: replace the evaluator
apply: true
max: 15
```
`capture: {}` is the same as `capture: true`. This mirrors the
[verify](/guides/verify) schema deliberately: `custom` plays the role of
`verify.criteria` (tune the built-in), `agent` plays the role of `verify.judge`
(replace it), and setting both is a parse error with the same message style.
### deliberate human learning
The Learn checkbox, `--remember`, and manual add are the standard human path.
They are not automatic capture channels: the reviewer explicitly decides which
comments become durable. Ordinary approval comments affect the current run only.
### `tool-errors` (addon)
```yaml theme={"system"}
learning:
capture:
addons: [tool-errors]
```
Learns a failed tool call followed by a **corrected** call and a confirmed
success. Its value is that the verification happens **in code**, not in a
prompt: a record is stored only when the run's trace contains the failed call,
a later successful call of the same tool, and a different input on the retry. A
retry with identical input that happened to work is flakiness, not a lesson,
and is not captured.
The stored record carries the tool, a normalized failure signature, and both
calls as evidence:
```markdown theme={"system"}
### [error-fix] browser.uploadFile: files.length remained #
When browser.uploadFile fails with "files.length remained #", use the corrected call shape that succeeded: {"path":"/Users/me/shot.png"}
```
Because these records capture mechanics rather than policy, they cannot conflict
with your instructions, so they skip the model-judged vet below. They dedupe by
`(tool, failure signature)` and supersede structurally (one record per failure
mode, replaced when a better recovery is observed), and they never go through
the free-text merge path in [tidy](#tidying-up).
### `custom` (scoped free-form)
```yaml theme={"system"}
learning:
capture:
custom: |
Only capture rules about selectors and page structure.
Ignore anything about content or tone.
```
The built-in evaluator, now allowed to extract from the execution itself and
scoped by your guidance text. Free-form candidates carry no structural proof, so
they rest entirely on the [vet](#every-candidate-is-vetted), which is why the
channel is opt-in and its candidates never skip vetting.
### `agent` (evaluator replacement)
```yaml theme={"system"}
learning:
capture:
agent: ./capture.agentuse
```
An `.agentuse` file replaces the built-in evaluator for free-form capture, the
same pattern as `verify.judge`. The path resolves relative to the agent file
that declares it. The capture agent receives the run's evidence and the
learnings the agent already carries with their ids, and records its result by
calling `submit_learnings` once with 0-5 candidates:
```yaml theme={"system"}
---
model: anthropic:claude-haiku-4-5
---
# Capture Evaluator
Read the run and record only rules about API pagination and rate limits.
Never record anything about the content the agent produced.
```
Replacing the evaluator does not buy a bypass. Its candidates still pass the
common vet, provenance stamping, and lifecycle validation. Deliberate human
learning stays on the separate Learn/`--remember` path either way; it never
depends on a user-supplied capture agent behaving.
A nested `learning:` or `verify:` block on the capture agent is ignored (a
helper pass must not recurse into a tree of helper passes), and a capture agent
that suspends on an approval gate is an error.
`learning: true` makes no post-run evaluator call. The built-in evaluator runs
only when `capture.custom` is configured; use `capture.agent` when that
automatic judgment is genuinely domain-specific.
## Configuration Options
| Option | Type | Description |
| - | - | - |
| `learning: true` | `boolean` | Apply learnings explicitly saved through Learn, `--remember`, or manual add. Automatic observation remains off. |
| `capture` | `boolean \| object` | Automatic observation configuration. `true` or `{}` enables no automatic channel; name `addons`, `custom`, or `agent` to opt in. Default `true` for compatibility. |
| `capture.addons` | `string[]` | Typed, structurally-verified channels. `tool-errors` is the only entry today. Defaults to `[]`. |
| `capture.custom` | `string` | Guidance that scopes free-form observation capture through the built-in evaluator. Mutually exclusive with `agent`. |
| `capture.agent` | `string` | Path to an `.agentuse` file that replaces the built-in evaluator, relative to this agent file. Mutually exclusive with `custom`. |
| `apply` | `boolean` | Inject vetted, active learnings into instructions before each run. Defaults to `true`. |
| `max` | `number` | How many rules this agent keeps, and therefore how many apply per run. Defaults to `15`, range 1-50. Enforced when capture writes, not just when rules are injected, see [An agent keeps 15 rules](#an-agent-keeps-15-rules-not-15-of-many). Each one is paid for on every model request; `agentuse doctor` prints the token cost. |
| `model` | `string` | Model for the helper calls (capture, vet, and tidy-up). Defaults to the agent's own model. |
**`criteria` was removed in v0.19.0** and is a hard parse error:
```
"criteria" was removed — free-form capture is opt-in now. To restore scoped
free-form capture, move it to capture: { custom: "..." }
```
The only faithful mapping would keep free-form policy capture running
automatically, which is exactly what the redesign exists to stop, so the
rewrite is yours to make consciously. Setting both `custom` and `agent` is
likewise a parse error: `set either "custom" (built-in evaluator) or "agent"
(agent file), not both`.
Two keys were removed in v0.17.0 and remain rejected by name: `evaluate` (long
deprecated) and `file` (a custom learnings path, now that learnings live
outside your repository, see [Storage](#storage)). An agent file still
carrying one fails loudly rather than quietly ignoring it.
## Every candidate is vetted
Nothing becomes active on the strength of having been extracted. Every free-form
candidate, corrections included, is checked against the agent's **complete**
instructions, the rules already in force, and the run's own trace, before it can
be injected into anything.
| Verdict | What it means | What happens |
| - | - | - |
| **pass** | Genuinely new, consistent with the contract and the rules in force, and supported by the run | Becomes active |
| **duplicate** | Restates something the instructions or an active rule already say, in any wording | Model-authored: rejected. Human correction: quarantined |
| **contradiction** | Conflicts with the instructions or an active rule, or narrows one so far the two cannot both be satisfied | Quarantined, with the conflicting text named |
| **ungrounded** | The trace contradicts the claim, or does not contain the events it describes | Rejected. Never raised against a human-authored entry |
Two properties are worth stating plainly:
* **Human corrections are never dropped.** A reviewer's rule that fails the vet
is quarantined with the reason, not discarded. If the vet call itself fails,
corrections are stored active and observation candidates are dropped.
Free-form capture's entire safety case is the vet, so it fails closed while
human input fails open.
* **The vet sees the whole contract.** The fixed 3,000-character truncation that
used to hide every rule past the cut is gone. On any real agent that
truncation is what let the evaluator "rediscover" an explicit instruction as a
brand-new learning.
### Quarantine
A quarantined entry is set aside, never injected, and never deleted. It stays
visible with its reason in `agentuse learnings `, the serve UI's Learnings
panel, and `agentuse doctor`:
```
2 learnings quarantined (failed the vet, never injected):
[warning] Reuse the prior run item on same-day re-invocation — contradicts the contract: "Every invocation creates one new run item and terminalizes it"
[tip] Always resolve ids with store_list — duplicates the contract: "a type name is not an item ID; never call store_get on one"
```
The second one is a reviewer's own note. A model-authored duplicate would have
been rejected outright, with nothing lost: the rule already exists. A human
wrote that one, so it is kept and shown instead.
The fix is one of two things, and the reason line tells you which: correct the
agent file so the rule is no longer in conflict, or discard the rule.
Typed `tool-errors` records skip this step. They are verified structurally in
code, and they describe mechanics rather than policy, so there is nothing for
them to contradict.
## Rules are stamped with the instructions they were checked against
Every stored learning records the hash of the agent instructions it was captured
(or last re-vetted) against, alongside its channel, source session, and
evidence. The hash covers your own instructions with the machine-managed
[graduated block](#what-makes-a-learning-permanent) excised, so a rule
graduating never marks every other rule stale.
When you rewrite the agent file, the hash no longer matches and the affected
rules go **stale**:
* Stale rules are **held out of injection**. A rule vetted against instructions
that no longer exist does not get to keep applying unexamined.
* The next capture or `agentuse learnings tidy` **re-vets** them against the
current instructions: passes are re-stamped and start injecting again,
failures are quarantined with the reason. Nothing is deleted.
* Rules with **no hash at all**, anything captured before v0.19.0, are *not*
stale. They stay injectable until the first capture or tidy backfills them.
`agentuse doctor` says so when it matters:
```
learned guidelines: 12 of 15 applied, ~1.8k tokens/model request
3 learnings are stale: the instructions changed since they were vetted. They are held out of injection until the next capture or tidy re-vets them.
```
## Storage
Learnings are stored in the AgentUse state directory, alongside session logs, not in your repository:
```
$AGENTUSE_DATA_DIR/project/{project-hash}/
├── session/ # execution logs
├── consolidations/ # tidy-up undo snapshots
└── learnings/
└── agents/blog/write.learnings.md # one agent's learnings
```
`$AGENTUSE_DATA_DIR` defaults to `~/.local/share/agentuse`; when it is unset, `$XDG_DATA_HOME/agentuse` remains the standards-compatible fallback. `{project-hash}` is a digest of your git root, so two repositories that both contain `agents/blog/write.agentuse` keep separate learnings, and one agent resolves to one file whichever directory you run it from. The file itself is named after the agent's path relative to the project root, so subdirectories are preserved.
That path is not one you can type from memory, so nothing asks you to:
```bash theme={"system"}
agentuse learnings ./blog-writer.agentuse --path # print it
agentuse learnings ./blog-writer.agentuse --edit # open it in $EDITOR
```
`agentuse doctor ./blog-writer.agentuse` prints it too, as does `agentuse learnings ./blog-writer.agentuse --json` in its `file` field. Every learnings file also records which agent it belongs to, on the line under its heading:
```markdown theme={"system"}
# Learnings for write
```
### Why it is not next to your agent file
Every run rewrites this file, not only the runs that capture something: injecting a learning updates its counters. Kept in the repository, that is a permanently dirty working tree and a stream of commits carrying no decision.
The file was never meant to be the durable artifact. It is a staging buffer; your agent file is the thing that gets diffed and reviewed, and [graduation](#what-makes-a-learning-permanent) is how a proven learning crosses over into it.
**The trade:** learnings are no longer in git. There is no backup, no teammate sharing, and nothing survives a machine rebuild. The state directory holds locally generated data, like session logs. Graduation is the supported path into version control: a rule that has earned its way into your `.agentuse` file is committed, reviewable, and travels with the repository.
Renaming or moving an agent file also starts its learnings over, because the file is keyed by the agent's path. Rules already graduated into the agent file move with it and are unaffected.
### Moving learnings from before v0.17.0
Learnings used to live beside the agent file, named after it: `blog-writer.agentuse` paired with `blog-writer.agentuse.learnings.md`. That location is no longer read, not as a fallback, not once. Move them:
```bash theme={"system"}
agentuse learnings migrate --all
git commit -am "chore: move learnings to the agentuse state dir"
```
```
agentuse learnings migrate [|--all] [--dry-run] [--keep-source|--delete-source]
```
Name one agent file, or pass `--all` to walk every `.agentuse` file under the project root.
**It copies first and asks before deleting anything.** Once the copies are on disk it lists the originals and asks once whether to remove them; anything other than an explicit yes leaves them alone. Deleting files out of your repository is not something a migration should do on its own, so the destructive half is always yours to confirm. `--delete-source` answers yes up front (for scripts and non-interactive shells, where nothing is ever deleted without it), `--keep-source` answers no, and `--dry-run` reports what would be copied without writing anything.
It refuses rather than merges when the destination already holds learnings, and it lists any `*.learnings.md` with no agent file of that name as **orphaned, not migrated**. Those are usually left behind by a rename, and this is the only place they are ever mentioned.
If you skip the migration, the agent simply starts with an empty learnings store. Graduated rules are unaffected. The old files sit inert until you delete them, which is itself the point: inert means they stop churning.
A run that finds learnings stranded at the old location says so once, and so do `agentuse doctor` and the learnings panel in the serve web UI:
```
learnings found at the old location for agents/blog/write.agentuse
agents/blog/write.agentuse.learnings.md
No longer read. Move them: agentuse learnings migrate --all
```
This reads only whether that file exists, never what is in it, so the agent behaves identically with or without it. It keeps saying so even after the agent has captured new learnings into the new location, that is exactly when a populated panel makes a half-migrated agent look healthy.
## How capture works
After a run finishes with an automatic channel configured:
1. **Gather candidates per channel.** `custom` uses the built-in evaluator,
`agent` runs the replacement evaluator, and `tool-errors` scans the run's
tool traces in code. Deliberate human learnings are saved immediately by the
Learn/`--remember` path rather than inferred here.
2. **Vet the free-form candidates** against the complete contract, the rules in
force, and the trace. Passes become active, contradictions and failed human
corrections are quarantined, and model-authored duplicates and ungrounded
claims are rejected.
3. **Stamp provenance** (channel, source session, evidence, and the instruction
hash) and write to the store, enforcing `max`
([the cap](#an-agent-keeps-15-rules-not-15-of-many)).
4. **Re-vet stored rules the contract has moved out from under**: anything
stale, and anything with no hash at all, is checked against the current
instructions and either re-stamped or quarantined. This is what backfills a
pre-v0.19.0 store the first time capture runs after an upgrade.
The result is reported in the run's output and in the session log:
```
Extracted 2 learning(s), 1 quarantined → ~/.local/share/agentuse/project/…/blog-writer.learnings.md
```
## Deliberate Learning from Review Comments
At an [Approval Gate](/guides/approval-gates), a comment normally revises the
current run and nothing more. Check **Learn from this comment** when AgentUse
should remember the feedback for similar future situations. That explicit
choice is what makes the comment durable.
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
approval: true
learning: true
---
# Blog Writer
...
```
The same comment serves both purposes: it revises the current work, and when
checked, the learning processor grounds it in the reviewed output and rewrites
it as appropriately scoped guidance. For example, “this intro is too salesy”
can become “For informational posts, keep intros factual rather than
promotional,” not the universal rule “Never use promotional language.”
Checking Learn works even when the agent has no learning configuration; the
guidance is stored but reaches future runs only when `learning.apply` is enabled.
Explicit human learnings are stored as `src:manual` and rank ahead of automatic
observations. The CLI equivalent is:
```bash theme={"system"}
agentuse sessions resume 01K... \
--comment "Please revise this pass with citations" \
--remember "Always include source links before publishing."
```
A note you write this way is reconciled against the rules the agent already
carries, exactly as a captured learning is. If it restates or **contradicts** one
of them, it replaces that rule rather than being filed beside it, and the run
names what it replaced:
```
[Learning] Replaced an earlier rule: "Cite the source inline" (archived, id:a1b2c3d4)
```
This matters most on this path, because `--remember` is what you reach for when
you are correcting an earlier note of your own. Left unreconciled, the rule and
its own correction both stay in force, and the agent has to satisfy two
instructions that disagree.
A note can also collide with the agent file itself rather than with another
rule. It is saved either way, but quarantined rather than injected, and the run
says which instruction it conflicts with:
```
[Learning] Saved but quarantined "Publish drafts without review": contradicts the contract: "Never publish without an approval gate". It will not be injected; resolve the conflict in ./blog-writer.agentuse or discard the rule.
```
## How Application Works
On next run or approval resume (when `apply: true`):
1. Loads the agent's active rules from storage, skipping quarantined and
[stale](#rules-are-stamped-with-the-instructions-they-were-checked-against) ones
2. Injects the top `max` of them (15 by default) as a `## Relevant Learnings` section
3. Counts the injection against each rule's `injectedCount`
The runtime tells the model to apply each learning only when its situation is
relevant, preserve its intended scope, and never let it override the current
task or authored agent instructions. A clearly relevant learning can refine a
soft skill default without becoming a universal checklist item.
Learnings that have [graduated](#tidying-up) live in your agent file's own
`## Learned Guidance` block. Graduation changes storage and reviewability, not
these contextual semantics.
**`injectedCount` counts cost, not value.** It is how many runs a rule was
paid for on, and it is never evidence the rule worked. The effectiveness
signal is `approvedRuns` (runs the rule was in force for that ended in an
approval with no comment), and that is what
[graduation](#what-makes-a-learning-permanent) is gated on. The store field was named `applied:` before v0.19.0 and is read
as an alias; files are rewritten with `injected:` on the next save.
### An agent keeps 15 rules, not 15 of many
`max` is how many rules an agent **keeps**, not how many of a larger pile get
injected. Capture enforces it when it writes, so the set stays small enough that
every rule in it has been weighed against every other one.
That last part is the reason for the cap, and it matters more than the token
cost. While the store could grow without limit and only the top slice was
injected, nothing ever compared one rule against another. An agent could hold
two corrections that could not both be satisfied - captured weeks apart, from
separate rejections, each perfectly reasonable alone - and nothing would notice.
So when the set is full, a new learning has to be paid for. In order:
1. **Fold.** The evaluator sees every rule the agent already carries, each with
its id, and is asked to reconcile rather than merely avoid duplicating. If its
new learning restates, sharpens, or *contradicts* an existing rule, it returns
**one** rule that satisfies both, naming the id it replaces. The replaced rule
is retired, not deleted.
2. **Trade.** Nothing related in the set? The weakest auto-extracted rule is
retired to make room - but only if the new rule is worth more than the one it
displaces, so the set keeps the best rules rather than the last ones.
Once the set is full this applies to reviewer corrections too. They cannot be
traded away, so for them the answer is always to fold. That is the part that
keeps the set at its size.
Folding is not picking a winner. The merged wording has to carry every case the
originals covered, and the model writing it can see all of them. Two things are
never evicted: a rule you wrote or approved, and a rule you have repeated. A
repeat means the wording is not landing, which is a reason to rewrite it, not to
drop it.
Precedence within the set is unchanged - rules you saved yourself, then reviewer
comments, then self-extracted - with the most recent first inside each group.
### When a correction does not fit
If the capture model returns a correction without naming a rule to fold it into,
and no auto-extracted rule is left to trade away, the correction is kept anyway,
outside the cap. It is not dropped - losing a reviewer's correction because a
helper model failed to pick an id would be worse. But a rule outside the cap is
never injected, so the run tells you plainly:
```
learned guidelines: 15 of 16 applied, ~1.8k tokens/model request
1 correction(s) sit outside this agent's 15-rule limit and do NOT reach it -
they could not be folded into an existing rule, and no auto-extracted rule was
left to trade away.
Fold the set down: agentuse learnings tidy ./blog-writer.agentuse
```
This should be rare. If it is not, the corrections are carrying what your agent
file should have said, and the fix is in the instructions rather than the store.
A rule outside the cap cannot recover on its own. It is never injected, so
nothing about it is ever observed, and it is a human correction so it is never
evicted either. Left alone it stays there having no effect. This is why a full
set folds rather than grows - an earlier design let corrections accumulate past
the cap, and one agent reached 70 of them, permanently unreachable.
A store written before the cap was enforced can hold far more than `max`. The
first capture after upgrading drains the excess by retiring auto-extracted
rules from the bottom of the ranking - the ones that were not reaching the
model anyway. Nothing is deleted, and rules you wrote or repeated are never
touched, so the drain tends to *promote* a starved correction into force.
## Tidying up
When learnings outgrow the cap, or the agent file has been rewritten under them,
one action gets them back in order:
```bash theme={"system"}
agentuse learnings tidy ./blog-writer.agentuse
```
or the **Tidy up** button in the serve UI, on the session view and the agent's
Learnings tab. Both run the same thing. It makes six kinds of change:
* **re-vet** every rule that is stale or was never vetted against the current
instructions, re-stamping the ones that still hold and **quarantining** the
ones that no longer do, with the reason
* **merge** near-duplicates into one rule
* **rewrite** a learning you have repeated, a repeat means the wording is not
landing, so restating it sharply is the fix
* **retire** what has been superseded. A retired rule is removed, and re-asserting
it later simply adds it back
* **graduate** the learnings that have proven themselves into the agent's own
instructions, where they apply on every run and cost no cap slot
* **rewrite the permanent block** in your agent file as one document, combining
rules that overlap and dropping any another rule now fully states
The re-vet pass is why a tidy-up is worth running after you edit an agent file,
even on a set that is comfortably under the cap: it is what gets stale rules
injecting again, and what backfills a store captured before v0.19.0.
That last change is the only thing that ever makes the permanent block smaller.
Graduation alone only ever added to it, so on a long-running agent it accumulated
the same way the staging file did, and more expensively: those rules apply on
every single run. The rewrite reads the whole block at once, which is what lets
it combine two rules that are halves of one procedure, or fold a correction into
the rule it corrects.
Two things check the result, because it edits a file you wrote:
* **Nothing may vanish.** Every rule that goes in must come back inside some
rule, or be named as dropped with a reason. If one goes missing the whole
rewrite is discarded rather than written.
* **Nothing may be quietly summarised away.** Each rewritten rule is then
audited against the originals it claims, and asked what instructions it no
longer carries, a case, a threshold, an exception, a worked example. Anything
reported missing puts those originals back untouched, and the rest of the
rewrite still applies.
The audit asks about meaning, not length. A merge that halves the wording while
keeping every instruction passes; one that keeps the length but drops an
exception does not. That matters because the tidy-up is supposed to make the
block *denser*, shorter for the same instructions, and a length-based check
would have blocked exactly the merges worth having.
It applies immediately and then shows you what changed: a summary, the rules that
became permanent named individually, each edit to the permanent block, and the
diff of **both** files. Undo with
`agentuse learnings undo ./blog-writer.agentuse` or the Undo button, which covers
the re-vet pass along with everything else.
```
$ agentuse learnings tidy ./blog-writer.agentuse
reading 58 learnings to see what repeats…
rewriting 4 rules…
pass 2: reading 41 learnings to see what repeats…
pass 2: rewriting 3 rules…
writing both files…
Done
3 merged, 1 rewritten, 12 retired, 2 quarantined, 9 now permanent — 58 → 15 in force
```
Each pass reads every learning still in force, so a pass takes about a minute.
It runs in two stages: first it decides which learnings relate to which, in
small groups weighed in parallel, then it writes each replacement rule in its own
call, again in parallel.
**One tidy-up keeps going until another pass would not help.** A single pass is
cautious by design, and it compares learnings in small groups, so two
duplicates that never share a group both survive it. Rather than making you press
the button again, the tidy-up goes back over whatever is left, up to five passes,
and stops as soon as a pass frees no slot. It all happens in memory: both files
are written once at the end, so however many passes it took, one tidy-up is one
Undo.
In the web UI it runs on its own page, counting the rules as it writes them and
naming the pass it is on; leaving that page does not stop it, and the result
waits there with its Undo button. The agent's Learnings tab links back to the
last tidy-up (`Tidied up 5m ago, see what changed or undo it`) for as long as it
is undoable, whether it was run from the browser or the terminal.
### When it ends still over the cap
That is a normal ending for a well-used agent, not a failure, so the result says
which rule kept each learning that is still in force:
```
Still 20 over the cap, and that is as far as tidying up can take it.
The rest are still there for a reason:
18 say different things, so there is nothing left to merge them into
2 are less than 14 days old, and a new learning gets that long to prove
itself before it can be retired
None of the corrections still in force can move into the agent file yet. That
takes 3 runs approved without a comment, or 10 runs in force; the closest of
them has been applied in 6. They become eligible on their own as the agent
keeps running.
```
The counts add up to the number still in force, so nothing is unaccounted for.
When pressing again genuinely would get further (the five passes ran out, or a
group of learnings could not be planned), it says so instead.
"You wrote it by hand" is not on that list, and used to be. A rule you typed
was once exempt from retirement entirely, which sounds protective and is not:
the only thing that can retire one of your rules is a later correction of your
own, and a veto put that out of reach. One agent reached 85 corrections it
could neither apply nor consolidate. Authorship now weighs heavily in the
judgement instead of ending it. What still cannot be retired is a rule you have
**repeated**, a repeat means the wording is not landing, so it gets sharpened
rather than dropped.
Inspect first with `agentuse learnings ./blog-writer.agentuse` (a list by status)
or `agentuse learnings tidy ./blog-writer.agentuse --dry-run` (the plan and both
diffs, nothing written).
### What makes a learning permanent
Graduation is earned, not guessed. A learning qualifies when any of:
* **you repeated it** (`re:` above zero), saying the same thing twice is the
clearest evidence a rule matters, or
* **it was in force across 3 runs you approved without leaving a comment.**
Approving with no notes is a vote for every rule that applied that run; a run
you commented on credits nothing, because you had to correct something, or
* **it has been in force for 10 runs.** Surviving that long without ever being
contradicted is weaker evidence than the other two, but it is evidence, and
without it a rule nobody comments on either way waits forever.
Writing a rule yourself does not graduate it on its own. It used to, and the
result was that hand-written rules went permanent before they had ever been
checked against the rules already there.
Graduated rules are written into your agent file inside a marked block:
```markdown theme={"system"}
## Learned Guidance
Guidance consolidated from previous runs. Apply each learning only when its situation is relevant. Preserve its intended scope; do not turn examples or past incidents into universal requirements. The current task and the agent's authored instructions take precedence. A clearly relevant learning may refine a soft skill default:
- [tip] Cite sources before publishing
```
Only the bytes inside the markers ever change; your frontmatter, comments and
formatting are left exactly as they were. Because the block is part of the agent
file, it is diffable, reviewable in a pull request, and readable by a teammate
who wants to know what this agent has been taught. Re-running the tidy-up
replaces the block rather than appending a second copy.
The block in the file is the source of truth for these rules, not a printout of
one held elsewhere: the tidy-up reads it back before every edit, so wording you
change by hand survives, and is what the next rewrite works from.
The block is also excluded from the instruction hash, so a rule graduating never
makes the rest of the set stale. Rules still on probation are injected under a
separate `## Relevant Learnings` heading, so the two tiers never collide.
Graduation is skipped, and the result says so, when the agent file is not
writable. Nothing else can stop it: there is one learnings file per agent,
so making a rule permanent never affects another agent.
## Seeing what capture is doing
"Capture is producing junk" should be measurable, not anecdotal. Three surfaces
show the same numbers.
`agentuse learnings ` lists every rule by status, grouped:
```
Applied (12 of 15)
applied [warning] Keep intros factual
src:approval · injected:31 · ch:corrections · approved:4 · ready to make permanent · 2026-07-02 · id:a1b2c3d4
Stale — instructions changed, awaiting re-vet (3)
dormant [tip] Cite the primary source, never a summary
src:approval · injected:12 · ch:corrections · 2026-07-19 · id:e5f6g7h8
Quarantined (2)
quarantined [tip] Reuse the prior run item on same-day re-invocation
src:auto · injected:0 · ch:custom · 2026-08-14 · id:i9j0k1l2
why: contradicts the contract: "Every invocation creates one new run item"
```
`agentuse doctor ` adds the per-channel breakdown and the token cost:
```
learned guidelines: 12 of 15 applied, ~1.8k tokens/model request
3 learnings are stale: the instructions changed since they were vetted. They are held out of injection until the next capture or tidy re-vets them.
learnings file: ~/.local/share/agentuse/project/a1b2c3/learnings/blog-writer.learnings.md
by channel: corrections:11, tool-errors:4, custom:2, legacy:3
2 learnings quarantined (failed the vet, never injected):
[tip] Reuse the prior run item on same-day re-invocation — contradicts the contract: "Every invocation creates one new run item"
```
`legacy` in that breakdown is entries captured before channels existed.
The serve UI's Learnings panel shows the same states with quarantine reasons
inline, and links to the last tidy-up.
Everything is agent-operable: `agentuse learnings --json` reports
`cap`, `active`, `injected`, `dormant`, `stale`, and `quarantined` counts at the
top level, and each entry carries its full record plus computed `state`,
`injected`, and `stale` flags. `agentuse learnings tidy --dry-run` prints the
plan without writing. No step in the lifecycle needs a human at a terminal, so a
scheduled maintenance agent can do the cleanup.
## Learning Categories
Learnings are categorized for context:
* **tip** - General best practices
* **warning** - Things to avoid
* **pattern** - Successful approaches
* **tool-usage** - How to use specific tools
* **error-fix** - Solutions to known errors (the `tool-errors` channel always uses this one)
### How long a learning should be
A captured rule is written as an order, not an explanation: one behaviour, a few
sentences, and under 800 characters. It keeps the specifics that change what the
agent does - a threshold, a trigger, an exception, the one example that shows
what the rule means - and drops the incident it came from. Dates, session ids,
names and quoted complaints are almost never load-bearing.
This matters more than it looks. A rule too long to hold beside its peers cannot
be compared against them, and comparison is what stops two contradicting rules
being in force at once. If a rule needs headings or numbered sections, it is more
than one rule.
## Storage Format
Learnings are stored as readable markdown:
```markdown theme={"system"}
# Learnings for blog-writer
### [tip] Use specific examples over generic advice
When writing productivity tips, include concrete scenarios
like "checking emails before coffee" rather than abstract advice.
### [error-fix] browser.uploadFile: files.length remained #
When browser.uploadFile fails with "files.length remained #", use the corrected
call shape that succeeded: {"path":"/Users/me/shot.png"}
### [tip] Cite sources before publishing
Always include source links before publishing.
### [tip] Reuse the prior run item on same-day re-invocation
On a same-day re-invocation, reuse the run item the previous invocation created.
```
Every field except the date is optional, so older files load unchanged, and
unknown tokens are ignored rather than rejected:
* `src:` records who authored it, `auto` (an evaluator), `approval` (promoted from a reviewer comment), or `manual` (explicitly saved by a reviewer). Files without it load as `auto`.
* `ch:` records the capture channel, one of `corrections`, `tool-errors`, `custom`, `agent`. Absent on entries written before channels existed.
* `ih:` is the [instruction hash](#rules-are-stamped-with-the-instructions-they-were-checked-against) the rule was last vetted against. Absent on entries that predate it; those count as fresh, not stale, until a capture or tidy backfills them.
* `injected:` counts injections into a run's prompt. `applied:` is the pre-v0.19.0 name and reads as an alias; the file is rewritten with `injected:` on the next save.
* `tool:` and `sig:` are the `tool-errors` dedupe key, the tool and its normalized failure signature.
* `sess:` is the session the rule was captured in.
* `state:graduated` means the rule now lives in the agent file and this staged copy is on its way out. `state:quarantined` means it failed the vet and is never injected; the reason is on the `` line beneath. Absent means active. A `state:retired` entry in an older file is skipped on read and dropped on the next write, so retired rules do not accumulate.
* `re:` counts how many times a human repeated the learning; `ok:` counts the approved, uncommented runs it was in force for. These are the evidence the tidy-up uses to decide what to rewrite and what to make permanent.
* `` carries the one-line evidence trail, for `tool-errors` the failed and corrected calls.
The `` line under the heading is a breadcrumb, so a file sitting in the state directory can be traced back to the agent that wrote it. Nothing reads it back; it is there for you.
## Upgrading an existing agent
No migration is needed and no file moves. Existing learnings files load as they
are; the first capture or tidy after the upgrade backfills the instruction hash
and vets the entries it finds, quarantining rather than deleting anything that
no longer holds. `undo` covers that pass like any other.
The dividing rule for config: **hard-error and quit when honoring the key would
resurrect risky behavior or the config contradicts itself; warn once and
continue when the faithful mapping is strictly safer than what you had.**
Nothing is ever silently ignored.
| What you have | What happens | Behavior |
| - | - | - |
| `learning: true` | Warns once, continues | Applies deliberately saved human learnings. Ordinary comments affect only the current run and free-form capture stops. The warning names the explicit form and is echoed by `agentuse doctor`. |
| `capture: true` | Still parses; meaning narrows | Old meaning: free-form auto-capture. New meaning: no automatic observation channels. Human learning uses Learn/`--remember`; a one-time notice names `capture: { custom: "..." }` as the way to restore scoped free-form capture. |
| `capture: false` | Unchanged | Capture off. |
| `apply: true` / `apply: false` | Unchanged | Same boolean, same meaning; `true` now injects only vetted, active, non-stale learnings. |
| `criteria: "..."` | **Hard error, agent quits** | The only mapping that honors it would keep free-form policy capture running automatically. Rewrite it as `capture: { custom: "..." }`; the error and `doctor` both say so. |
| `custom` + `agent` both set | **Hard error, agent quits** | A contradiction the parser cannot resolve. Pick one. |
| `evaluate`, `file` | **Hard error** (unchanged) | Rejected by name since v0.17.0. |
| `max`, `model` | Unchanged | |
If you were relying on free-form capture and want it back, the one-line answer
is a `custom` block naming what is worth keeping:
```yaml theme={"system"}
learning:
capture:
custom: |
Capture rules about tone and sourcing. Ignore anything about
scheduling, tooling, or this run's specific content.
```
If you reached for `apply: false` to stop bad auto-captured rules from reaching
the agent, try turning it back on. The vet is what `apply: false` was standing
in for, and it discriminates: it drops the junk instead of throwing away the
valid corrections along with it.
## Example: Manual Review Workflow
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
learning:
capture:
custom: Keep rules about structure and hooks; ignore anything about a specific post.
apply: false
---
# Blog Writer
Write short productivity blog posts (150-200 words).
## Requirements
- Start with a relatable hook
- Include 3 actionable tips
- End with a clear call-to-action
```
After 5-10 runs, review what it captured with `agentuse learnings ./blog-writer.agentuse` (a list by status) or `agentuse learnings ./blog-writer.agentuse --edit` (the file itself):
```markdown theme={"system"}
### [tip] Use specific examples over generic advice
When writing productivity tips, include concrete scenarios
like "checking emails before coffee" rather than abstract advice.
### [pattern] Structure with time estimates
Each actionable tip should include a specific time estimate
(e.g., "5-minute brain dump") to make it feel achievable.
```
Then update your agent instructions with the best insights:
```yaml theme={"system"}
## Requirements
- Start with a relatable hook
- Include 3 actionable tips with specific time estimates # ← from learnings
- Use concrete scenarios, not abstract advice # ← from learnings
- End with a clear call-to-action
```
This keeps you in control while still benefiting from extracted patterns.
## Best Practices
The default channel is the one a human authored. Run on it for a while before opening free-form capture with `custom` or `agent`
When you do enable `custom`, say what is worth keeping *and* what to ignore. An unscoped evaluator finds something every run
A quarantined rule names the instruction it collided with. That is usually a defect in the agent file worth fixing, not just a bad rule
Rewriting instructions makes rules stale and holds them out of injection. `agentuse learnings tidy` re-vets them and graduates the proven ones
## Next Steps
Persistent data storage for agents
Orchestrate teams of learning agents
# macOS Desktop App
Source: https://docs.agentuse.io/guides/macos-desktop
Run the AgentUse dashboard as a native macOS menu-bar app
AgentUse for Mac keeps scheduled agents, approvals, and active runs available
from the menu bar without leaving a Terminal window open. It can start quietly
at login, opens the operations dashboard in its own window, and includes the
complete AgentUse runtime, so Node.js and a separate CLI installation are not
required. The app and CLI use the same projects and session history, letting you
move between Desktop and Terminal without duplicate setup or configuration.
## Install
Download the signed DMG from the
[latest GitHub release](https://github.com/agentuse/agentuse/releases/latest),
open it, and move **AgentUse** to Applications. Open AgentUse from Applications
to start setup.
## First launch
The Desktop setup screen has two independent options:
* **Launch AgentUse at login** starts the app quietly in the menu bar so
schedules, approvals, and background runs remain available. It is selected
by default but is not added to macOS Login Items until you select
**Continue**.
* **Add CLI launcher** creates `~/.local/bin/agentuse`, pointing to the CLI
bundled inside AgentUse.app. It is optional and never blocks **Continue**.
After **Continue**, Desktop joins the same onboarding flow as the Web UI: create
a project, run the credential-free sample, connect a runtime provider, and hand
the first agent to your coding assistant. Desktop reads provider status from
the same bundled runtime that will run the agent. If login is required, the
coding agent stops and asks you to run it in Terminal rather than passing
credentials or OAuth details through coding-agent chat.
After you copy the first-agent prompt, onboarding stays on the current screen
and checks for the new agent. When it appears, select **Open agent** to review
and run it. If creation takes too long, you can copy the prompt again or check
for the agent manually.
## Command line launcher
The optional launcher makes the bundled CLI available at:
```text theme={"system"}
~/.local/bin/agentuse
```
`~/.local/bin` must be on your shell's `PATH` before a bare `agentuse` command
can resolve to it. Desktop does not edit shell configuration automatically.
Settings lists every executable named `agentuse` found on the login-shell
`PATH`, in resolution order. The first path is the command the shell runs when
you enter `agentuse`. You can add or replace the launcher at
`~/.local/bin/agentuse` even when npm, pnpm, Bun, Yarn, Homebrew, or another
installation exists elsewhere. Desktop never modifies those other
installations.
Use **Add**, **Replace**, or **Remove** in Settings to manage only the bundled
launcher. If a different installation appears first, either call the displayed
launcher path directly or change your shell's `PATH` order.
## Global shortcut
The global shortcut is off by default so AgentUse does not take over a key
combination used by macOS or another app. Record one in Settings to show or hide
the Dashboard from anywhere.
Open **Settings → General** and select the shortcut button to record a different
combination. Hyper shortcuts are supported: the star in `✦ A` represents
Control+Option+Command+Shift (`⌃⌥⌘⇧`), including Caps Lock mappings that emit
those modifiers. Select **Clear** to disable the shortcut. If macOS or another
app already owns a combination, AgentUse keeps the previous working shortcut
and asks you to choose another.
## How it behaves
Launching AgentUse opens the dashboard. Closing the window hides it without
stopping the backend, so schedules, approvals, and active runs remain available.
Use the AgentUse menu-bar icon to:
* show the AgentUse dashboard
* open Settings
* quit AgentUse
Settings shows whether the local server is running, lets you start or stop a
server owned by the desktop app, configures launch at login and the CLI
launcher, controls native approval and session-completion notifications, and
displays the current server log. The Settings window uses native
SwiftUI controls while the dashboard remains the existing web interface. A
server started outside the app is identified as external and is never stopped
by the desktop controls. If that external server restarts, Desktop keeps its
port available and reconnects instead of starting a competing server. Use
**Start Server** explicitly if the external server has been retired and you
want Desktop to replace it. Login launches start in the background so the menu-bar
status and approvals are available without opening the dashboard window.
The dashboard gear opens **Dashboard preferences** for theme, Home layout,
session list style, and reloading the dashboard. Select **Open Mac Settings…**
there for server, login, shortcut, CLI, native notification, and log controls.
## Updates
AgentUse checks quietly for updates on a recurring schedule while the menu-bar
app is running, without requiring Settings or the dashboard to stay open, and
downloads available updates in the background. When an update is ready, choose
**Restart Now** in the native prompt or **Later** to keep working. You can also
open **Settings → About** to check manually or restart and install a downloaded
update. AgentUse never installs an update without an explicit restart decision.
Closing the Dashboard, using Command+Q, or choosing Quit
from the Dock hides the app without stopping its backend. Only **Quit AgentUse**
from the menu-bar item fully exits the app and stops a backend it started. A
backend that was already running when the app launched is left alone. Only one
desktop app instance can run at a time.
When the app owns the running server, choosing **Quit AgentUse** from the
menu-bar item asks for confirmation and explains that the server will stop with
the app. Choose **Keep AgentUse Running** and hide the Dashboard window instead
when schedules and approvals should remain available in the background.
The desktop window accepts only the loopback dashboard origin. Links to normal
`http` or `https` sites open in the default browser; other external navigation
is blocked. Electron renderer access to Node.js is disabled and context
isolation is enabled.
## Troubleshooting
If the window does not load, open **Settings** from the menu-bar item and check
the server status and **Logs** tab. You can also use
the CLI independently:
```bash theme={"system"}
agentuse serve ps
agentuse serve logs
```
See [Operations Dashboard](/guides/serve-dashboard) for dashboard behavior and
[CLI Commands](/reference/cli-commands) for the full `serve` reference.
Run the Desktop app from source, install local builds, and create signed releases.
# Developing AgentUse for Mac
Source: https://docs.agentuse.io/guides/macos-desktop-development
Run, package, sign, and notarize the AgentUse macOS app
This page is for contributors working on the AgentUse Desktop app. For normal
installation and usage, see [macOS Desktop App](/guides/macos-desktop).
## Requirements
Desktop development requires:
* Node.js 22 or later
* Bun and pnpm
* Xcode, including its command-line tools
Xcode is required because the build compiles the native SwiftUI Settings helper
and uses Apple's asset-catalog compiler for the app icon.
## Run from source
From the repository root, install workspace dependencies, build the CLI and Web
UI, then start Electron:
```bash theme={"system"}
pnpm install
bun run build
pnpm desktop:dev
```
The Desktop process attaches to a registered `agentuse serve` daemon when one
is already running. Otherwise it starts the compiled local CLI on a loopback
port. The browser dashboard remains available at the URL shown in the menu.
Set `AGENTUSE_CLI_PATH` to test against a specific CLI build:
```bash theme={"system"}
AGENTUSE_CLI_PATH=/absolute/path/to/bin/cli.js pnpm desktop:dev
```
## Install a local build
For routine testing, install and launch one canonical app copy:
```bash theme={"system"}
pnpm desktop:install-local
```
The installer builds in temporary staging, gracefully terminates running
AgentUse Desktop copies, replaces `~/Applications/AgentUse.app`, and launches
that copy. Avoid opening `apps/desktop/dist/*/AgentUse.app` directly; using one
canonical installation prevents Launch Services from retaining several copies
with the same bundle identifier.
## Package the app
Create a package for the current Mac architecture:
```bash theme={"system"}
pnpm desktop:package:mac
```
For an unsigned development package:
```bash theme={"system"}
CSC_IDENTITY_AUTO_DISCOVERY=false pnpm desktop:package:mac
```
The Settings helper builds for the current architecture by default. For a
universal `arm64` and `x86_64` package, include both architectures in the nested
SwiftUI helper:
```bash theme={"system"}
AGENTUSE_SETTINGS_UNIVERSAL=1 pnpm desktop:package:mac
```
The package includes the AgentUse runtime, dashboard, built-in skills, and
required metadata. Source, tests, prior Desktop builds, and workspace caches are
excluded.
## Sign and notarize a release
For a manual release, store notarization credentials in the login Keychain so
the app-specific password does not enter shell history:
```bash theme={"system"}
xcrun notarytool store-credentials agentuse-notary \
--apple-id \
--team-id
APPLE_KEYCHAIN_PROFILE=agentuse-notary pnpm desktop:package:mac
```
`notarytool` prompts securely for the app-specific password. electron-builder
uses the Developer ID Application identity installed in the login Keychain.
For CI, configure repository Actions secrets named `MAC_CSC_LINK` and
`MAC_CSC_KEY_PASSWORD`, plus `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, and
`APPLE_TEAM_ID`. The certificate value is the base64-encoded Developer ID
Application `.p12`. Keep all signing credentials in CI secrets. Hardened runtime
is enabled, and the packaged native Settings helper is placed under
`Contents/Frameworks` before notarization.
## Prepare an updater-enabled release
The root package and Desktop app share one release version. Use the repository
release script to prepare that version; do not edit the Desktop version
separately:
```bash theme={"system"}
bun scripts/release.ts prepare X.Y.Z
```
Push the prepared tag to the public repository. After the portable release gate
passes, GitHub Actions builds on native Apple Silicon and Intel runners. Each
package is signed, notarized, stapled, and verified before it is preserved as a
workflow artifact. The publishing job merges their update metadata and uploads
two DMGs, two Mac ZIPs, four blockmaps, and one `latest-mac.yml` to the release.
Every artifact filename includes `arm64` or `x64`, and the merged metadata lists
both architectures so electron-updater selects the matching ZIP.
Confirm the completed GitHub Release contains that nine-file set. Test the feed
from an older signed build on each architecture: confirm that the update
downloads in the background, choose **Later** in the native prompt, install it
from **Settings → About**, and confirm the new version launches. Repeat with
**Restart Now**, then repeat a check while offline and confirm the app continues
working while the About tab reports the failure.
# Manager Agents
Source: https://docs.agentuse.io/guides/manager-agents
Orchestrate teams of agents with delegation, tracking, and scheduling
The `type: manager` configuration and orchestration behavior are experimental
and may change without migration. Discuss feedback in
[GitHub Discussions](https://github.com/agentuse/agentuse/discussions).
## What are Manager Agents?
Manager agents are specialized agents designed for orchestration. Instead of doing work directly, they coordinate teams of subagents, track progress, and make decisions about what work to delegate next.
## When to Use Manager Agents
Use a manager agent when you need to:
* **Coordinate multiple specialists** - Different agents for research, writing, review, etc.
* **Track complex workflows** - Multi-phase projects with dependencies
* **Run scheduled operations** - Regular tasks that span multiple runs
* **Maintain state across runs** - Track what's done, what's pending, what's blocked
## Basic Configuration
Set `type: manager` in your agent frontmatter:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
type: manager
subagents:
- path: ./researcher.agentuse
- path: ./writer.agentuse
---
# Content Manager
## Goal
Create articles on trending topics.
## SOP
1. Research trending topics
2. Write articles for each topic
3. Review and publish
```
## Configuration Options
### Required
* `type: manager` - Enables manager mode with orchestration prompts
### Recommended
* `subagents` - Team of agents to delegate to
* `store` - Persistent storage for tracking work items
### Optional
* `schedule` - Cron expression for scheduled runs
## The Manager Prompt
When `type: manager` is set, your agent automatically receives instructions with orchestration guidelines. You don't need to write these yourself - they're included automatically.
### Automatic Orchestration Loop
The manager follows this loop automatically (shown for reference - you don't need to include this in your agent file):
1. **UNDERSTAND** - Parse goal and SOP from your instructions
2. **CHECK** - Review current state (pending work, in-progress items)
3. **DECIDE** - Determine what needs to happen next based on goal and state
4. **DELEGATE** - Call subagents with clear, specific instructions
5. **TRACK** - Update store items with outcomes from delegation
6. **REPEAT** - Continue until the goal is achieved or no further progress can be made
This means you only need to define your **Goal** and **SOP** - the manager handles the orchestration mechanics.
### Schedule Awareness
If your manager has a `schedule`, it receives context about run frequency:
```yaml theme={"system"}
---
type: manager
schedule: "0 9 * * *" # Daily at 9 AM
---
```
The manager learns to pace work appropriately - not rushing to complete everything in one run if there's time, checking progress vs targets before starting new work.
## Work Tracking with Store
Managers work best with a persistent store:
```yaml theme={"system"}
---
type: manager
store: "my-project" # Shared store name
subagents:
- path: ./researcher.agentuse
- path: ./writer.agentuse
---
```
All subagents can share the same store by using the same store name. This enables coordination without explicit communication.
See [Store Guide](/guides/store) for available store tools.
## Writing SOPs (Standard Operating Procedures)
A good SOP clearly defines the workflow phases:
```markdown theme={"system"}
## SOP (Standard Operating Procedure)
### Phase 1: Research
- Use the researcher to find 3 interesting topics
- Store each topic with type "topic" and status "pending"
### Phase 2: Writing
- For each pending topic, delegate to the writer
- Update status to "in_progress" when started
- Update status to "written" when complete
### Phase 3: Review
- For each written article, delegate to the reviewer
- If approved, update status to "done"
- If revisions needed, send back to writer
### Completion
- All items should have status "done"
- Summarize completed work
```
## Complete Example: Content Team
### Manager Agent
```yaml theme={"system"}
# manager.agentuse
---
model: anthropic:claude-sonnet-5
type: manager
store: "content-pipeline"
schedule: "0 * * * *" # Every hour
subagents:
- path: ./agents/researcher.agentuse
- path: ./agents/writer.agentuse
- path: ./agents/reviewer.agentuse
---
# Content Team Manager
## Goal
Produce 3 high-quality articles per day.
## SOP
### Phase 1: Topic Discovery
- Check store for pending topics
- If fewer than 3 pending topics, use researcher to find more
- Store topics with type "topic", status "pending"
### Phase 2: Writing
- For each pending topic, delegate to writer
- Pass topic context and target word count (500 words)
- Store article with type "article", parentId = topic id
### Phase 3: Review
- For each unreviewed article, delegate to reviewer
- If approved, mark article as "done"
- If revisions needed, mark as "needs_revision" with feedback
### Completion Criteria
- 3 articles with status "done" today
- Report progress and any blockers
```
### Researcher Subagent
```yaml theme={"system"}
# agents/researcher.agentuse
---
model: anthropic:claude-haiku-4-5
store: "content-pipeline"
---
You are a research specialist. Find trending topics.
When given a research task:
1. Search for trending topics in the specified area
2. Evaluate each topic for article potential
3. Create store items for promising topics
Return a summary of topics found.
```
### Writer Subagent
```yaml theme={"system"}
# agents/writer.agentuse
---
model: anthropic:claude-sonnet-5
store: "content-pipeline"
---
You are a content writer. Create engaging articles.
When given a writing task:
1. Get the topic from the store using the provided ID
2. Research and write a compelling article
3. Create a store item for the article linked to the topic
4. Update the topic status to "written"
Return the completed article.
```
### Reviewer Subagent
```yaml theme={"system"}
# agents/reviewer.agentuse
---
model: anthropic:claude-haiku-4-5
store: "content-pipeline"
---
You are an editor. Review articles for quality.
When given a review task:
1. Get the article from the store
2. Check for: accuracy, clarity, engagement, grammar
3. Either approve (update status to "done") or request revisions
Return your review decision with feedback.
```
## Delegation Guidelines
When managers delegate to subagents:
Be specific about what you need. Include context from previous work.
```
writer({
task: "Write a 500-word article about AI productivity tools",
context: { topicId: "...", keywords: [...], targetAudience: "..." }
})
```
So subagents can update the same items:
```
reviewer({
task: "Review article for publication",
context: { articleId: "01HX...", topicId: "01HW..." }
})
```
What output do you expect? What quality bar?
```
task: "Write article. Must include: 3 actionable tips, real examples, conclusion with CTA"
```
## Handling Blockers
Managers should stop and report when blocked:
```markdown theme={"system"}
## When Blocked
If I need human input, I will:
1. State what I'm blocked on
2. Explain what decision/input I need
3. List available options if applicable
Example blockers:
- Need approval for topic selection
- External resource required (API key, credentials)
- Quality issue that requires human judgment
```
## Best Practices
Each subagent should have one clear purpose
Track all work items in the store, not in prompts
Define phases, transitions, and completion criteria
Don't rush if you run frequently
## Debugging Manager Agents
### Enable Verbose Logging
```bash theme={"system"}
agentuse run manager.agentuse --verbose
```
### Check Store State
```bash theme={"system"}
# View store contents
cat .agentuse/store/content-pipeline/items.json | jq
```
### Test Subagents Independently
```bash theme={"system"}
# Run subagent directly
agentuse run ./agents/writer.agentuse "Write about AI tools"
```
## Next Steps
Learn about persistent data storage
Run managers on a schedule
Deep dive into subagent configuration
See complete manager examples
# Model Configuration
Source: https://docs.agentuse.io/guides/model-configuration
Configure AI providers and models for your agents
## Overview
AgentUse supports multiple AI providers. You need to authenticate with at least one provider to run agents.
## Supported Providers
Claude models (Opus, Sonnet, Haiku)
Anthropic API-key authentication
GPT models including GPT-5, GPT-4, GPT-4o
Supports OAuth and API keys
Access to 100+ models via unified API
API key authentication
Low-cost open coding models curated by OpenCode
API key authentication
Claude, Llama, Mistral, Nova and more via AWS
AWS SigV4 or Bearer token
Any OpenAI-compatible endpoint: Ollama, LM Studio, vLLM, llama.cpp, etc.
## Naming a Model Without a Version
Pinning an exact model id means editing every agent file when a new release
ships. Three ways to avoid that, in increasing order of scope:
**1. Drop the version.** A model id with its version left off means "the newest
in this line":
```yaml theme={"system"}
---
model: anthropic:claude-sonnet # newest Sonnet
model: openai:gpt-mini # newest small GPT
---
```
The lineup behind these aliases is refreshed each AgentUse release, so an alias
always points at a model the release shipped with. A real model id always wins
over an alias, so anything you pin keeps its exact meaning. See
[Version Aliases](/reference/models#version-aliases) for the current table.
**2. Name your own.** A `models.aliases` block in `~/.agentuse/config.json` lets
one edit repoint every agent that uses it:
```json theme={"system"}
{
"models": {
"aliases": { "fast": "anthropic:claude-haiku", "smart": "anthropic:claude-opus" }
}
}
```
```yaml theme={"system"}
---
model: "@fast"
---
```
An alias can also carry an ordered fallback list:
```json theme={"system"}
{
"models": {
"aliases": {
"smart": {
"candidates": ["anthropic:claude-opus", "openai:gpt"],
"cooldown": "5m"
}
}
}
}
```
AgentUse falls back when an execution segment cannot get started on a candidate:
a transient first-request failure (rate limit, timeout, provider 5xx, transport
error), or a model it cannot authenticate to at all (no login, an OAuth token
that will not refresh, a 401/403). This includes a segment resumed after an
approval gate. Either way it only happens before the model emits new output or
invokes a tool in that segment. The selected model and remaining ordered
fallback policy are persisted for later resumes. `cooldown` keeps new runs in
the same process
from repeatedly waiting on a model that just failed; it resets when the process
restarts.
**3. Set a default and stop naming models.** With `models.default` (or
`AGENTUSE_MODEL`) configured, `model:` becomes optional:
```json theme={"system"}
{ "models": { "default": "anthropic:claude-sonnet" } }
```
Aliases resolve to concrete models before execution, so session logs and cost
accounting record the model that actually ran. A suspended run first resumes on
its last selected model, even if the alias has moved since; a fallback-eligible
failure before new output may then advance through its persisted policy.
To migrate agent files you already have, `agentuse models unpin` swaps pinned
versions for aliases (`--dry-run` to preview), and `agentuse models bump` moves
stale pins forward for files you want to keep pinned.
## Authentication Methods
### 1. Interactive Login (Recommended)
The simplest way to authenticate:
```bash theme={"system"}
# Interactive menu
agentuse provider login
# Or login to specific provider
agentuse provider login openai
agentuse provider login openrouter
agentuse provider login opencode-go
```
Anthropic API keys remain built in. Claude Pro/Max OAuth is supplied by the
shortlisted community plugin and can be installed from provider setup or from
the CLI:
```bash theme={"system"}
agentuse plugins install cb7337/agentuse-claude-code-provider@v0.1.0
agentuse provider login anthropic
```
Users upgrading with an Anthropic OAuth credential created by the former core
flow do not need to run these commands. AgentUse installs the pinned
compatibility plugin and adopts that credential automatically. The explicit
community-plugin installation flow is shown only for new configuration.
Community providers that use an external CLI can also appear during onboarding
when their required executable is on the AgentUse server's PATH. Installing one
uses that CLI's existing credentials and runs the provider's readiness check
before continuing. If the check fails, setup shows the provider's error and
setup instructions. Installed CLI providers remain available for retrying setup.
### 2. Environment Variables
Set API keys as environment variables:
```bash theme={"system"}
# Add to ~/.bashrc, ~/.zshrc, or ~/.profile
export ANTHROPIC_API_KEY="sk-ant-api03-..."
export OPENAI_API_KEY="sk-proj-..."
export OPENROUTER_API_KEY="sk-or-v1-..."
export OPENCODE_GO_API_KEY="..."
```
### 3. Configuration File
Create a `.env` file in your project:
```bash theme={"system"}
# .env
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-proj-...
OPENROUTER_API_KEY=sk-or-v1-...
OPENCODE_GO_API_KEY=...
```
### Advanced Environment Variable Configuration
AgentUse supports flexible environment variable patterns for multiple API keys:
```bash theme={"system"}
# Using environment suffixes for different keys
export ANTHROPIC_API_KEY_DEV=sk-ant-api03-dev-key
export ANTHROPIC_API_KEY_PROD=sk-ant-api03-prod-key
export OPENAI_API_KEY_PERSONAL=sk-proj-personal-key
export OPENCODE_GO_API_KEY_TEAM=opencode-go-team-key
# Then specify in model string
agentuse run agent.md --model anthropic:claude-sonnet-5:dev
agentuse run agent.md --model openai:gpt-5.6:OPENAI_API_KEY_PERSONAL
agentuse run agent.md --model opencode-go:kimi-k2.7-code:OPENCODE_GO_API_KEY_TEAM
```
Never commit `.env` files to version control! Add to `.gitignore`:
```
.env
.env.local
.env.*.local
```
## OpenCode Go
OpenCode Go provides curated open coding models through a low-cost OpenCode subscription. AgentUse treats it as a built-in provider and automatically routes each model to the correct OpenCode Go API shape.
```bash theme={"system"}
agentuse provider login opencode-go
agentuse run agent.agentuse -m opencode-go:kimi-k2.7-code
agentuse run agent.agentuse -m opencode-go:minimax-m3
agentuse run agent.agentuse -m opencode-go:qwen3.7-plus
```
Or configure it with an environment variable:
```bash theme={"system"}
export OPENCODE_GO_API_KEY="..."
```
OpenCode Go publishes its live model list at `https://opencode.ai/zen/go/v1/models`, so `opencode-go:` model IDs are passed through rather than validated against AgentUse's static model registry.
## Amazon Bedrock
Bedrock authenticates with standard AWS credentials rather than `agentuse provider login`. Three modes are supported (in priority order):
**1. Static IAM access keys (SigV4)**
```bash theme={"system"}
export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
# Optional, for STS / assumed-role temporary credentials
export AWS_SESSION_TOKEN="..."
```
**2. Bedrock API key (Bearer token)**
```bash theme={"system"}
export AWS_REGION=us-east-1
export AWS_BEARER_TOKEN_BEDROCK="..."
```
**3. AWS SDK credential provider chain**, used automatically when neither of the above is set. Resolves `AWS_PROFILE`, `~/.aws/credentials`, SSO cache, EC2/ECS/EKS instance roles, etc.
```bash theme={"system"}
# Refresh SSO / assume-role credentials for your profile, then run:
export AWS_REGION=eu-west-1
export AWS_PROFILE=my-bedrock-profile
agentuse run agent.agentuse -m bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0
```
Use the full Bedrock model ID (which contains colons) as-is, or an inference profile ARN:
```bash theme={"system"}
agentuse run agent.agentuse -m bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0
agentuse run agent.agentuse -m bedrock:meta.llama3-70b-instruct-v1:0
agentuse run agent.agentuse -m bedrock:arn:aws:bedrock:eu-west-1:123456789012:application-inference-profile/abcd1234
```
Your IAM user/role needs `AmazonBedrockFullAccess` (or an equivalent custom policy) and you must have requested access to the foundation model in the AWS console. The `bedrock:` prefix bypasses the static model registry, so any Bedrock model ID or inference-profile ARN is accepted.
## Custom Providers
Connect hosted or local endpoints from **Dashboard Settings → Providers**. A
custom provider can use OpenAI Chat Completions, OpenAI Responses, or Anthropic
Messages. Dashboard setup discovers available models, lets you choose which to
save, and verifies the selected protocol with a minimal completion before the
provider is ready. Saved custom providers remain editable in Settings.
The CLI supports adding OpenAI-compatible endpoints such as Ollama, LM Studio,
vLLM, and llama.cpp.
### Adding a Custom Provider
```bash theme={"system"}
# Ollama (default port 11434)
agentuse provider add ollama --url http://localhost:11434/v1
# LM Studio (default port 1234)
agentuse provider add lmstudio --url http://localhost:1234/v1
# With optional API key
agentuse provider add myserver --url https://my-gpu-server.example.com/v1 --key sk-mykey123
```
### Using Custom Providers
In your agent file:
```yaml theme={"system"}
---
model: ollama:glm-5-flash:q4_K_M
---
```
```yaml theme={"system"}
---
model: lmstudio:qwen/qwen3.5-9b
---
```
Or override at runtime:
```bash theme={"system"}
agentuse run agent.agentuse -m ollama:glm-5-flash:q4_K_M
agentuse run agent.agentuse -m lmstudio:qwen/qwen3.5-9b
```
Custom providers support colons in model names, `ollama:qwen3.5:0.8b` is parsed as provider `ollama`, model `qwen3.5:0.8b`.
### Environment Variable Overrides
Custom providers support env var overrides using the uppercased provider name:
```bash theme={"system"}
# Override base URL and API key for a custom provider named "ollama"
export OLLAMA_BASE_URL=http://192.168.1.100:11434/v1
export OLLAMA_API_KEY=sk-optional-key
```
### Managing Custom Providers
```bash theme={"system"}
# List all providers (including custom)
agentuse provider list
# Remove a custom provider
agentuse provider remove ollama
```
**Local model limitations:**
* **Quality**: Small models (under 30B parameters) often struggle with complex tool use, multi-step reasoning, and following detailed agent instructions. For best results, use 30B+ parameter models.
* **Context window**: Ensure your model is loaded with a context size of at least 8192 tokens. AgentUse's system prompts can exceed 4096 tokens.
* **Tool calling**: Many local models have limited or no native tool/function calling support, which may cause agents with tools to fail or behave unpredictably.
## Managing Credentials
### List Stored Credentials
```bash theme={"system"}
agentuse provider list
```
Output:
```
📁 Credentials stored in: ~/.local/share/agentuse/auth.json
Stored credentials:
🔑 anthropic (Claude subscription OAuth) → Use as: anthropic:claude-sonnet-5
🎫 openai (api) → Use as: openai:gpt-5.6
Environment variables:
🌍 openrouter (OPENROUTER_API_KEY) → Use as: openrouter:z-ai/glm-5.3
Custom Providers:
🔌 ollama → http://localhost:11434/v1 (stored), key ****abcd (from OLLAMA_API_KEY)
🔌 lmstudio → http://localhost:1234/v1 (stored)
```
### Remove Credentials
```bash theme={"system"}
# Remove specific provider
agentuse provider logout anthropic
# Remove a custom provider
agentuse provider remove ollama
```
### Rotate API Keys
```bash theme={"system"}
# Logout and login again
agentuse provider logout openai
agentuse provider login openai
```
## Getting API Keys
Get API keys from provider consoles:
* **Anthropic**: [console.anthropic.com](https://console.anthropic.com) → API Keys → Create Key (starts with `sk-ant-api03-`)
* **OpenAI**: [platform.openai.com](https://platform.openai.com) → API Keys → Create new secret key (starts with `sk-proj-`)
* **OpenRouter**: [openrouter.ai](https://openrouter.ai) → Keys → Create Key (starts with `sk-or-v1-`)
* **OpenCode Go**: [opencode.ai/auth](https://opencode.ai/auth) → Subscribe to Go → Copy API key
Keys are shown only once. Store them securely and never commit to version control.
## Authentication Priority Order
AgentUse checks authentication sources in this order:
1. **OAuth tokens** - Checked first and refreshed automatically
2. **Stored API keys** (via `agentuse provider login`) - Stored in `~/.local/share/agentuse/auth.json`
3. **Environment variables** - `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `OPENCODE_GO_API_KEY`
4. **Custom environment variables** - Using suffix patterns (e.g., `ANTHROPIC_API_KEY_DEV`) or full variable names
## Runtime Model Override
Override the model at runtime using the `--model` flag:
```bash theme={"system"}
agentuse run agent.agentuse --model anthropic:claude-haiku-4-5
agentuse run agent.agentuse -m openai:gpt-5.4-mini
agentuse run agent.agentuse -m opencode-go:kimi-k2.7-code
agentuse run agent.agentuse -m anthropic:claude-sonnet # version alias
agentuse run agent.agentuse -m @fast # configured alias
```
Without `--model`, a parent and each delegated sub-agent use their own declared
models. An explicit runtime override is run-wide: it applies at every sub-agent
depth, including the full candidate order of a fallback alias, and is preserved
when a session resumes.
See the complete reference for model override format, environment-specific keys, CI/CD examples, and sub-agent inheritance behavior.
## Multi-Provider Setup
Use different providers for different agents:
```markdown theme={"system"}
---
name: fast-agent
model: anthropic:claude-haiku-4-5 # Uses Anthropic
---
```
```markdown theme={"system"}
---
name: powerful-agent
model: openai:gpt-5.6 # Uses OpenAI GPT-5
openai:
reasoningEffort: high # More thorough reasoning
textVerbosity: medium # Balanced response length
---
```
```markdown theme={"system"}
---
name: specialized-agent
model: openrouter:z-ai/glm-5.3 # Uses OpenRouter
---
```
```markdown theme={"system"}
---
name: open-coding-agent
model: opencode-go:kimi-k2.7-code # Uses OpenCode Go
---
```
```markdown theme={"system"}
---
name: local-agent
model: ollama:glm-5-flash:q4_K_M # Uses local Ollama
---
```
## Provider Options
Configure provider-specific settings for fine-tuned model behavior:
### Reasoning Effort (recommended, provider-agnostic)
The simplest way to control how hard a model thinks is the top-level
`reasoning`. AgentUse normalizes the level to the selected model's supported
vocabulary, then applies the corresponding provider control. For example,
GPT-5.6 maps `minimal` to `low`, while modern Claude uses adaptive thinking, so
one setting works whether the agent runs on Claude or GPT-5:
```yaml theme={"system"}
---
model: anthropic:claude-opus-5
reasoning: high # none | minimal | low | medium | high | xhigh | max
---
```
Use `medium`/`high` for genuine judgment (hard multi-constraint calls, planning,
debugging), `low`/`minimal` for lighter work, omit for the model default, and
`none` to force reasoning off. It is opt-in and bills reasoning tokens at
**output rates**.
Reach for `reasoning` first. The provider-specific `openai.reasoningEffort`
and `anthropic.thinking.budgetTokens` below are escape hatches for exact wire-level control,
honored only when the top-level `reasoning` is unset. Being top-level,
`reasoning` also avoids a subtle trap: a provider-specific key placed at
the wrong nesting level is silently dropped (the agent parses and runs with the
tuning never applied).
### OpenAI Provider Options
For OpenAI models (especially GPT-5), you can control thinking effort and verbosity:
```yaml theme={"system"}
---
model: openai:gpt-5.6
openai:
reasoningEffort: high # Options: 'none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'
reasoningSummary: auto # Options: 'auto', 'detailed' — surface reasoning in the session trace
textVerbosity: low # Options: 'low', 'medium', 'high'
promptCacheRetention: 24h # Optional: extended prompt caching on supported models
---
```
**reasoningEffort**: Controls thinking effort for reasoning
* `none`: Disable reasoning when the selected model supports it
* `minimal`: Use the lightest reasoning mode
* `low`: Faster responses with less thorough reasoning
* `medium`: Balanced performance (default)
* `high`: More comprehensive reasoning, slower responses
* `xhigh`: Maximum reasoning for models that support it
**reasoningSummary**: Streams a natural-language summary of the model's reasoning so it appears inline in the session trace (`auto` or `detailed`). On reasoning-capable models this **defaults to `auto`**, the reasoning tokens are billed whether or not you ask for the summary, so surfacing it is near-free. Non-reasoning models (e.g. `gpt-4o`) omit it automatically.
**textVerbosity**: Controls response length and detail
* `low`: Concise, minimal prose
* `medium`: Balanced detail (default)
* `high`: Verbose, detailed explanations
**prompt caching**: AgentUse automatically sends a stable OpenAI `promptCacheKey` per agent so repeated runs with the same prompt prefix are easier for OpenAI to route to cache. You usually do not need to configure this. Set `promptCacheRetention: 24h` only when you want extended retention and the selected OpenAI model supports it.
If you omit `reasoningEffort`, `textVerbosity`, or `promptCacheRetention`, AgentUse leaves those fields unset and uses the OpenAI/AI SDK defaults. Reasoning effort is typically `medium` on reasoning models. `none`, `xhigh`, and `24h` retention are model-specific OpenAI options; if a model does not support a selected option, OpenAI will reject the request. Whether a reasoning summary actually streams also depends on the effort level and task complexity.
### Anthropic Provider Options
For Claude models, you can enable extended thinking so the model's reasoning streams into the session trace:
```yaml theme={"system"}
---
model: anthropic:claude-haiku-4-5
anthropic:
thinking:
budgetTokens: 4096 # Minimum 1024
---
```
Extended thinking is **off by default**, an explicit opt-in. Enabling it generates new thinking tokens billed at **output rates**, a real cost increase that scales with the budget (unlike OpenAI's `reasoningSummary`, where the reasoning is billed either way). AgentUse automatically raises `max_tokens` above the budget so Anthropic's `max_tokens > budget` constraint is met and there's headroom for the answer.
Only older Claude models such as Claude Haiku 4.5 accept a manual budget. Claude Opus 4.7 and later, Sonnet 5 and later, Fable, and Claude Haiku 5.5 reject it, so set their depth with `reasoning` instead.
These options help you optimize for:
* **Speed vs Quality**: Lower reasoning effort for faster responses
* **Conciseness vs Detail**: Lower verbosity for more direct answers
* **Cost Optimization**: Lower settings reduce token usage
* **Reasoning visibility**: `reasoningSummary` (OpenAI) and `thinking` (Anthropic) surface the model's "why" inline in the session view
## Troubleshooting
* Verify API key is correct
* Check key hasn't expired
* Ensure key has required permissions
* Try logging out and back in
* Check your API tier and limits
* Implement exponential backoff
* Consider upgrading your plan
* Use different keys for different projects
## CI/CD Authentication
For automated environments:
### GitHub Actions
```yaml theme={"system"}
name: Run Agent
on: [push]
jobs:
agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: pnpm install -g agentuse
- run: agentuse run my-agent.agentuse
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
OPENCODE_GO_API_KEY: ${{ secrets.OPENCODE_GO_API_KEY }}
```
### Docker
```dockerfile theme={"system"}
FROM node:20
RUN npm install -g pnpm && pnpm install -g agentuse
ENV ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
ENV OPENAI_API_KEY=${OPENAI_API_KEY}
ENV OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
ENV OPENCODE_GO_API_KEY=${OPENCODE_GO_API_KEY}
CMD ["agentuse", "run", "agent.agentuse"]
```
## Next Steps
Start using your authenticated providers
Build agents with your providers
# Plugins
Source: https://docs.agentuse.io/guides/plugins
# Plugins
An AgentUse plugin is an installable package. A plugin can contribute executable extensions today, with other resource types such as skills and agents able to use the same package boundary in the future.
An extension is a TypeScript or JavaScript module that exports one activation function. The function receives a stable API and registers events, providers, or provider patches. AgentUse waits for async activation before model discovery and execution begin.
```ts theme={"system"}
import type { AgentUseExtension } from "agentuse/plugin-api";
const extension: AgentUseExtension = async (agentuse) => {
agentuse.on("agent:complete", async (event) => {
agentuse.log.info(`${event.agent.name} completed`);
});
agentuse.registerProvider({
// provider definition
});
};
export default extension;
```
Extensions run as trusted code with the same operating-system permissions as AgentUse. Review third-party plugins before installing them.
## Loose project and global extensions
Single-file extensions are discovered automatically from the existing plugin directories:
* `.agentuse/plugins/*.{ts,js}` for the current project.
* `$AGENTUSE_CONFIG_DIR/plugins/*.{ts,js}` for every project (defaults to `~/.agentuse/plugins/*.{ts,js}`).
Project registrations are scoped to the current asynchronous execution, so concurrent server runs from different projects do not share project providers or event handlers.
The historical event-object format remains supported:
```ts theme={"system"}
export default {
"agent:complete": async (event) => {
console.log(event.result.text);
},
};
```
It is equivalent to calling `agentuse.on("agent:complete", handler)`. New extensions should use the activation API.
## Event API
`agentuse.on(event, handler)` returns a disposable registration. Handlers run sequentially in registration order and receive a context containing an abort signal. Logging stays on the activation API so handlers can close over `agentuse.log`.
```ts theme={"system"}
const registration = agentuse.on("agent:complete", async (event, context) => {
agentuse.log.info(`${event.agent.name}: ${event.result.text}`);
});
await registration.dispose();
```
There are three intercepting events and five observational events:
| Event | Can affect execution? | Purpose |
| - | - | - |
| `tool:call` | Mutate `event.input`; return `{ block, reason, terminate }` | Inspect, rewrite, or deny a tool call before AgentUse policy and execution |
| `tool:result` | Return `{ output, isError }` | Rewrite the result passed back to the model or recover/convert an error |
| `agent:complete` | Return `{ text }` | Rewrite the final outward response before channels and callers receive it |
| `agent:start` | No | Observe an execution starting |
| `agent:error` | No | Observe a terminal execution error |
| `agent:suspend` | No | Observe suspension for human approval |
| `agent:resume` | No | Observe an approval or continuation resume |
| `model:fallback` | No | Observe a model fallback before the next attempt |
Observational events and non-input fields are immutable snapshots. `tool:call` is the deliberate exception: every handler shares the same mutable `input` object, so later handlers, AgentUse approval policy, and the tool see prior mutations. Return-based transformations from `tool:result` and `agent:complete` are also chained through later handlers. A handler failure is logged and does not prevent later handlers from running.
### Intercepting tools
```ts theme={"system"}
agentuse.on("tool:call", async (event) => {
if (event.toolName === "search") {
event.input.limit ??= 10;
}
if (event.toolName === "bash" && event.input.command === "forbidden") {
return { block: true, reason: "Blocked by project policy", terminate: true };
}
});
agentuse.on("tool:result", async (event) => {
if (event.toolName === "search" && !event.isError) {
return { output: redactSecrets(event.output) };
}
});
```
`block` denies the tool call. `reason` is returned to the model. `terminate` stops the agent loop after the denied result instead of allowing another model turn.
### Transforming the final response
```ts theme={"system"}
agentuse.on("agent:complete", async (event) => {
return { text: addFooter(event.result.text) };
});
```
The replacement becomes the returned and delivered final text. The session timeline remains the raw streamed execution trace.
### Event shapes
```ts theme={"system"}
interface AgentReference {
name: string;
model: string;
description?: string;
filePath?: string;
}
interface AgentCompleteEvent {
agent: AgentReference;
result: {
text: string;
duration: number;
tokens?: number;
toolCalls: number;
toolCallTraces?: ToolCallTrace[];
finishReason?: string;
finishReasons?: string[];
hasTextOutput: boolean;
};
isSubAgent: boolean;
consoleOutput: string;
}
interface AgentStartEvent {
agent: AgentReference;
sessionId?: string;
trigger: "scheduled" | "manual" | "slack" | "api" | "onboarding";
}
interface AgentErrorEvent {
agent: AgentReference;
sessionId?: string;
error: { name?: string; message: string; code?: string };
duration: number;
}
interface AgentSuspendEvent {
agent: AgentReference;
sessionId: string;
reason: "approval";
toolCallId?: string;
approvalUrl?: string;
}
interface AgentResumeEvent {
agent: AgentReference;
sessionId: string;
reason: "approval" | "continue";
}
interface ModelFallbackEvent {
agent: AgentReference;
sessionId?: string;
from: string;
to: string;
reason: string;
attempt: number;
}
```
## Provider API
Register a provider with a unique model prefix, model catalog, transport, and optional authentication and prompt behavior:
```ts theme={"system"}
agentuse.registerProvider({
id: "acme",
name: "Acme Models",
models: [
{
id: "acme-large",
name: "Acme Large",
input: ["text", "image"],
reasoning: true,
contextWindow: 128_000,
maxOutputTokens: 16_384,
cost: { input: 0, output: 0 },
capabilities: { tools: true },
},
],
transport: {
kind: "openai-responses",
baseURL: "https://models.acme.test/v1",
},
});
```
Models are addressed as `acme:acme-large`. Declared model limits and modalities participate in validation, context compaction, output-token limits, media tools, and `agentuse models`.
### Model catalogs
Providers can declare models directly, inherit a built-in catalog, or discover models asynchronously during activation:
```ts theme={"system"}
models: { inherit: "anthropic", include: ["claude-sonnet-*"] }
```
An adapter can retain those model IDs while replacing transport-specific
metadata such as subscription pricing:
```ts theme={"system"}
models: {
inherit: "anthropic",
patch: { cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 } },
}
```
```ts theme={"system"}
models: async ({ fetch, signal }) => {
const response = await fetch("http://localhost:11434/v1/models", { signal });
return convertModels(await response.json());
}
```
### Transports
AgentUse includes declarative transports:
* `anthropic-messages`
* `openai-responses`
* `openai-chat-completions`
Use `custom` when a provider needs a different protocol or a subprocess-backed runtime:
```ts theme={"system"}
transport: {
kind: "custom",
apiVersion: 1,
async *stream(request, context) {
for await (const event of runCustomProtocol({
modelId: context.modelId,
messages: request.messages,
tools: request.tools,
signal: request.signal,
})) {
yield event;
}
},
}
```
The custom boundary is owned and versioned by AgentUse; extensions do not import AI SDK types or receive internal provider factories. A request contains normalized messages, function tools, tool choice, common sampling options, provider options, and an abort signal.
Custom streams emit these events:
* `warning` before any response output.
* `text-delta` and `reasoning-delta`, with optional stable block IDs.
* `tool-call` with an ID, name, and structured input.
* Optional `response-metadata` or `error` events.
* Exactly one terminal `finish` event with a normalized reason and optional token usage.
AgentUse adapts this contract to its internal model runtime. A stream that ends without `finish` is rejected. When the consumer cancels a run, the request's abort signal fires and the stream's iterator is closed, so check `request.signal` in long-running loops.
If the custom transport speaks a known wire protocol, say so with `protocol: "anthropic"` or `protocol: "openai"`. AgentUse then applies that protocol's behavior, such as Anthropic output-token limits and which `providerOptions` block reaches the model. Omit it for a bespoke API.
```ts theme={"system"}
transport: {
kind: "custom",
apiVersion: 1,
protocol: "anthropic",
async *stream(request, context) { /* ... */ },
}
```
### Authentication
AgentUse core owns restrictive credential-file permissions, credential persistence, cross-process refresh locking, status reporting, and deletion. Plugins return opaque credentials and implement provider-specific login, refresh, and request resolution.
```ts theme={"system"}
auth: {
methods: [{
id: "oauth",
type: "oauth",
name: "Acme SSO",
environment: ["ACME_TOKEN"],
async login(interaction, context) {
await interaction.openBrowser({ url: authorizationUrl });
const code = await interaction.prompt({
message: "Paste the authorization code:",
secret: true,
});
return exchangeCode(code, context.signal);
},
async refresh(credential, context) {
return refreshToken(credential, context.signal);
},
resolve({ credential }, context) {
const token = context.env.ACME_TOKEN ?? credential?.access;
return token ? { bearerToken: token, source: "Acme OAuth" } : undefined;
},
}],
}
```
Login interaction is UI-neutral and supports browser authorization, device codes, prompts, selections, and notifications. The same plugin therefore works in the terminal, desktop app, server, and CI environments.
Credentials with a numeric `expires` property are refreshed five minutes before expiry. AgentUse serializes refreshes and persists the returned credential before resolving request authentication. Declared environment credentials are resolved first, so an explicit process token is never blocked by an expired stored credential. When an adapter takes ownership of legacy provider OAuth, AgentUse moves it atomically into the adapter's method-specific credential slot.
### Readiness checks
A provider that needs something on the machine besides a credential, such as a
bridged local CLI, declares an optional `check()`. AgentUse runs it for
`agentuse provider list`, the dashboard Providers tab, and right after
`agentuse plugins install`, and refuses to build a model for the provider while
it fails, so an installed bridge never reports as connected when it cannot run.
```ts theme={"system"}
agentuse.registerProvider({
id: 'acme-cli',
name: 'Acme CLI',
models: discoverAcmeModels,
transport: { kind: 'custom', apiVersion: 1, stream: streamAcme },
async check({ env, signal }) {
try {
const version = await runAcme(['--version'], { env, signal });
return { ok: true, detail: `acme ${version}` };
} catch (error) {
return {
ok: false,
message: `Acme CLI not found: ${error.message}.`,
fix: 'npm install -g @acme/cli',
};
}
},
});
```
`detail` is shown beside the connected badge. `message` says what is missing
and `fix` is a command the user can run. A check that throws or takes longer
than ten seconds counts as not ready.
The dashboard Providers tab renders saved providers immediately, then updates
each row as readiness and recent connection checks finish. A row distinguishes
**Connected**, **Not verified** or **Not checked**, **Reconnect required**,
**Temporarily unavailable**, and **Not connected**, so a stored credential is
not presented as proof of a working connection. From the Plugins tab, **open in
Providers** uses a `?provider=` link that opens Settings with the matching
provider row expanded.
### Provider-owned prompts
Prompt contributions have stable IDs and ownership metadata:
```ts theme={"system"}
prompts: {
system() {
return [{
id: "identity",
content: "You are the Acme coding agent.",
position: "prepend",
portable: false,
}];
},
}
```
Non-portable contributions are removed when model fallback crosses providers. Their IDs are scoped to the registering provider; extensions do not need to compare raw system-message strings.
### Built-in provider adapters, patches, and overrides
A plugin can conditionally contribute a transport to an existing provider
namespace. The adapter is evaluated before the built-in transport; when its
predicate returns `false`, the built-in provider continues unchanged:
```ts theme={"system"}
agentuse.registerProvider("openai", {
name: "Acme SSO transport",
models: {
inherit: "openai",
patch: { cost: { input: 0, output: 0 } },
},
transport: {
kind: "openai-responses",
baseURL: "https://models.acme.test/v1",
},
auth: { methods: [acmeSso] },
async when(context) {
return Boolean(await context.auth.resolve("sso"));
},
priority: 100,
});
```
Registering an adapter does not activate it by itself. Its `when` function
receives the normal provider runtime context, including scoped authentication,
and is evaluated whenever AgentUse selects provider behavior. If several
adapters match, the highest `priority` wins; equal priorities retain plugin
registration order. The selected adapter owns transport, authentication,
model metadata, prompt contributions, and media capabilities for that request.
If `models` is omitted, the existing provider catalog and model IDs are
inherited unchanged.
A plugin can patch a built-in endpoint without replacing its models:
```ts theme={"system"}
agentuse.registerProvider("anthropic", {
baseURL: "https://proxy.acme.test/anthropic",
headers: { "X-Acme-Tenant": "engineering" },
});
```
A complete replacement must be explicit:
```ts theme={"system"}
agentuse.registerProvider({
id: "anthropic",
name: "Acme Anthropic",
override: true,
models: { inherit: "anthropic" },
transport: { kind: "anthropic-messages" },
});
```
Accidental built-in ID collisions are rejected. Registrations are removed when their plugin host is disposed.
## Distributed packages
### Curated provider plugins
AgentUse maintains a deliberately small, release-reviewed shortlist for the
provider setup experience. These plugins remain third-party executable code:
review their source and project status before installing them.
Browse the current choices in **Settings > Providers**. Each provider card
shows its publisher, reviewed version, installation source, and authentication
requirements. Community providers maintain their own setup instructions;
follow the linked repository for provider-specific credentials and limitations.
Some providers use credentials managed by an external application rather than
an AgentUse login.
The shortlist is bundled with AgentUse rather than fetched from a mutable
remote marketplace. A new or changed listing therefore goes through the normal
AgentUse release review.
The dashboard also exposes an advanced GitHub installation path. It requires an
explicit tag or full commit, reads only `package.json` before showing consent,
and installs the exact commit that was inspected. The resulting plugin is
labelled **Unreviewed**. Installed provider plugins can be updated or removed
from **Settings > Providers**; removing a package does not delete its saved
credential.
The v0.21 compatibility migration is narrower than normal installation: when
AgentUse finds an Anthropic OAuth credential written by the removed core flow,
it installs the pinned compatibility plugin and adopts the credential
without interrupting the user. New users still choose the plugin explicitly.
A Git repository package declares its resources in `package.json`:
```json theme={"system"}
{
"name": "@example/agentuse-provider",
"version": "1.0.0",
"keywords": ["agentuse-plugin"],
"peerDependencies": {
"agentuse": "*"
},
"agentuse": {
"apiVersion": 1,
"extensions": ["./src/index.ts"],
"providers": [
{ "id": "acme", "auth": ["oauth"] }
]
}
}
```
`agentuse.providers` is optional static metadata for the dashboard's safe
pre-install preview. It does not register the provider; the extension still
does that during activation. Extension entry paths must stay inside the plugin
package. Runtime dependencies belong in `dependencies`. Git installation uses
`npm install --omit=dev --ignore-scripts`; package lifecycle scripts never run
implicitly.
## Installing and managing packages
```bash theme={"system"}
agentuse plugins install owner/repository
agentuse plugins install git:github.com/owner/repository@v1
agentuse plugins install https://github.com/owner/repository.git
agentuse plugins list
agentuse plugins update
agentuse plugins update @example/agentuse-provider
agentuse plugins remove @example/agentuse-provider
agentuse plugins uninstall @example/agentuse-provider # alias
```
Use `-l` for project scope:
```bash theme={"system"}
agentuse plugins install -l ./my-plugin
agentuse plugins install -l owner/repository
agentuse plugins list -l
agentuse plugins update -l
agentuse plugins remove -l @example/agentuse-provider
```
`agentuse plugins install ./my-plugin` links the local directory directly, globally by default or into the project with `-l`. AgentUse validates and activates its current working tree without cloning it, so the folder does not need to be a Git repository and uncommitted edits are available on the next process start. Updating a linked plugin revalidates its manifest; removing it only removes the registry record and never deletes the source directory. `plugins update` reports "already up to date" when a linked package's version is unchanged or a source pinned to a tag or commit still resolves to the installed commit. Append a full commit SHA (`./my-plugin@`) to clone and pin a local Git checkout instead of linking it.
Global packages live under `$AGENTUSE_DATA_DIR/plugins`, which defaults to `~/.local/share/agentuse/plugins`. Managed project packages live under `.agentuse/packages`; linked plugins in either scope remain in their original directories. Both are recorded in `.agentuse/plugins.json`. `agentuse plugins list --all-scopes` displays every scope and marks linked entries.
Git tags, branches, and commits can be selected with `@ref`. Updates retain the configured ref. Git installation and updates clone into staging, install safe runtime dependencies, compile and activate every entry, and only then replace the active checkout. A failed validation leaves the working version in place.
The shorter `agentuse install|update|list|remove` commands remain as compatibility aliases.
# Remote Agents
Source: https://docs.agentuse.io/guides/remote-agents
Run agents directly from URLs
## Overview
AgentUse can execute agents directly from HTTPS URLs, enabling:
* Shared agent libraries
* Version-controlled agents
* Community agent repositories
* Dynamic agent loading
Remote agents must use HTTPS and have the `.agentuse` file extension for security.
## Running Remote Agents
### Basic Usage
```bash theme={"system"}
# Run from GitHub
agentuse run https://raw.githubusercontent.com/user/repo/main/agent.agentuse
# Run from your server
agentuse run https://example.com/agents/helper.agentuse
# Run from Gist
agentuse run https://gist.githubusercontent.com/user/id/raw/agent.agentuse
```
### With Arguments
```bash theme={"system"}
agentuse run https://example.com/agent.agentuse "Process this data"
```
## Security
Remote agents run with the same permissions as local agents. Always review the agent content before execution. Only run agents from trusted sources!
### Security Prompt
When running a remote agent, you'll see a security prompt:
```
⚠️ WARNING: You are about to execute an agent from:
https://example.com/agent.agentuse
Only continue if you trust the source and have audited the agent.
[p]review / [y]es / [N]o:
```
**Options:**
* `p` or `preview` - Show the agent content before deciding
* `y` or `yes` - Execute the agent immediately
* `N` or `no` - Abort execution (default)
## Performance
Remote agents are downloaded and executed directly without caching. Each run fetches the latest version from the URL, ensuring you always run the most up-to-date agent code.
## Publishing Agents
### GitHub Repository
1. Create a repository for your agents:
```
my-agents/
├── README.md
├── data-processor.agentuse
├── text-analyzer.agentuse
└── api-caller.agentuse
```
2. Access raw files:
```bash theme={"system"}
agentuse run https://raw.githubusercontent.com/username/my-agents/main/data-processor.agentuse
```
### GitHub Gist
1. Create a Gist with your agent
2. Get the raw URL
3. Share the URL for others to use
### Self-Hosted
Serve agents from your server:
```javascript theme={"system"}
// Express example
app.get('/agents/:name', (req, res) => {
const agentContent = getAgent(req.params.name);
res.type('text/plain').send(agentContent);
});
```
For local development, AgentUse allows HTTPS URLs with localhost or 127.0.0.1 and will accept self-signed certificates for these addresses only.
## Versioning
### Using Git Tags
```bash theme={"system"}
# Specific version
agentuse run https://raw.githubusercontent.com/user/repo/v1.0.0/agent.agentuse
# Latest stable
agentuse run https://raw.githubusercontent.com/user/repo/stable/agent.agentuse
# Development version
agentuse run https://raw.githubusercontent.com/user/repo/dev/agent.agentuse
```
### Version in URL
```bash theme={"system"}
# Semantic versioning in path
agentuse run https://example.com/agents/v2/processor.agentuse
agentuse run https://example.com/agents/v1/processor.agentuse
```
## Advanced Usage
### Dynamic Loading
Load agents based on conditions:
```javascript theme={"system"}
// Dynamic agent loader
const agentUrl = process.env.PROD
? 'https://prod.example.com/agent.agentuse'
: 'https://dev.example.com/agent.agentuse';
execSync(`agentuse run ${agentUrl}`);
```
### Agent Composition
Remote agents as sub-agents:
```yaml theme={"system"}
---
name: orchestrator
model: anthropic:claude-sonnet-5
subagents:
- path: https://example.com/agents/analyzer.agentuse
- path: https://example.com/agents/reporter.agentuse
---
```
### CI/CD Integration
For automation, you can use expect or other tools to handle the security prompt:
```yaml theme={"system"}
# GitHub Actions
name: Run Remote Agent
on: [push]
jobs:
agent:
runs-on: ubuntu-latest
steps:
- run: pnpm install -g agentuse
- run: |
echo "y" | agentuse run https://example.com/agents/ci-checker.agentuse \
"Check PR #${{ github.event.pull_request.number }}"
```
## Best Practices
AgentUse enforces HTTPS URLs to prevent man-in-the-middle attacks. HTTP URLs will be rejected.
Remote agents must have the `.agentuse` file extension for security validation.
Use the preview option to review agent code before execution in untrusted environments.
Include version information in URLs or use Git tags for reproducible deployments.
Clearly document what MCP tools and environment variables your agent needs.
## Example: Shared Team Agents
### Repository Structure
```
team-agents/
├── README.md
├── daily/
│ ├── standup.agentuse
│ └── report.agentuse
├── development/
│ ├── code-review.agentuse
│ └── test-runner.agentuse
└── deployment/
├── pre-deploy.agentuse
└── post-deploy.agentuse
```
### Team Usage
```bash theme={"system"}
# Daily standup
agentuse run https://raw.githubusercontent.com/team/agents/main/daily/standup.agentuse
# Code review
agentuse run https://raw.githubusercontent.com/team/agents/main/development/code-review.agentuse
# Deployment
agentuse run https://raw.githubusercontent.com/team/agents/main/deployment/pre-deploy.agentuse
```
## Troubleshooting
* AgentUse only accepts HTTPS URLs for security
* Ensure your URL starts with `https://`
* HTTP URLs will be rejected with an error
* Remote agents must have the `.agentuse` file extension
* Ensure your URL ends with `.agentuse`
* Ensure you're using the raw file URL, not the GitHub page URL
* For GitHub: use `https://raw.githubusercontent.com/...`
* Check if the repository is public
* Verify the branch/tag name
* Verify the URL is correct and accessible
* Check if corporate proxy or firewall is interfering
* Ensure the remote server has valid SSL certificates
## Security Checklist
* [ ] Only run agents from trusted sources
* [ ] Use the preview option to review agent code before running
* [ ] Ensure remote URLs use HTTPS and have `.agentuse` extension
* [ ] Implement access controls on agent servers
* [ ] Monitor agent execution logs
* [ ] Rotate API keys regularly
* [ ] Use environment-specific agents
* [ ] Verify server SSL certificates are valid
## Next Steps
Compose agents together
See remote agent examples
# Replay recorded inputs
Source: https://docs.agentuse.io/guides/replay
Test current instructions against a real session's recorded tool results, without live tool operations.
For instruction improvement, start with
`agentuse test result --session `: it supplies source evidence directly
without depending on matching tool calls. See [Testing agents](/guides/testing-agents).
This page documents the advanced strict-replay compatibility command.
Use replay when you are changing an agent's instructions and want to hold its
external inputs fixed:
```bash theme={"system"}
agentuse test agents/x/reply.agentuse --replay
```
The writer runs again. Its tools return recorded results instead of opening
browsers, running commands, updating stores, or starting child agents. No mock
model is needed. This is a fresh generation, not a continuation of the source
session.
## What stays fixed and what changes
* **Current:** the local agent definition and configured model, explicit
preloaded skills, applicable learnings, and explicitly granted read-only
reference files. Replay reads learnings without recording usage.
* **Recorded:** the original additional user prompt, tool schemas, external
results and errors. Relative dates use the original session's start date.
* **Withheld from the writer:** the old assistant draft, its approval proposal,
later revisions and human feedback. Those appear only in the comparison.
Explicit read-only **file** grants are snapshotted before generation so edits to
writing briefs take effect. Directory and wildcard grants stay recorded because
they may contain source data or drafts. The report lists refreshed files and
hashes; do not treat a refreshed data file as frozen evidence. Inline agent
instructions and preloaded skills are always current. Dynamic skill/tool
requests use their recordings.
## Where it stops
Replay captures the first `await_human` input **before gate preflight,
automated verification or human approval**. It does not grant approval, run
revisions, or publish. An agent that finishes without a gate yields its final
output. An explicit incomplete report remains incomplete.
A tool call without a matching recording stops the test with
`REPLAY_INPUT_MISSING`. No live lookup or LLM fabrication fills the gap.
The failed call and its exact inputs appear in the report.
Matching uses the tool name and arguments. Object key order and the narration
field `intent` do not matter; filesystem read paths are normalized. Other
arguments, including shell commands, URLs, prompts and array order, must match.
Repeated calls consume matching recordings in their original order.
`store_list` permits a different field projection when filters are identical and the requested page is contained in the recorded page and every requested value or known absence is recorded. Metadata
requests (such as `id` and `title`) use the metadata already present on each row.
Unknown data fields still stop the replay. Projection provenance appears in the report.
`store_create` writes to an isolated in-memory store with fresh `replay-` IDs.
Those items support `store_get`, `store_update`, and `store_delete`, so new drafts
can change without touching production. Queries after these writes are not yet
supported; replay stops rather than returning stale recorded lists.
Only recordings before the source's **first** approval gate are available.
For an ungated run, later user continuations are excluded. Mock and replay
sessions cannot be used as sources. An actively running source must first
finish or reach approval.
## Read the result
The CLI prints the old and new proposal/output and a path to `replay.json`.
With `--json`, it emits the structured comparison, refreshed-reference hashes,
per-call recording provenance and any mismatch:
```bash theme={"system"}
agentuse test agents/x/reply.agentuse --replay --json
```
The new session is marked as a test (`mock: true`) and stores
`config.replaySourceSessionId`. It does not modify or resume the original
session. Replay sessions cannot be resumed as live runs; run another replay to
try the next instruction change.
Exit status is 0 for a captured proposal or completed output, and 1 for a
mismatch, incomplete outcome or execution error. Success means the comparison
was captured, **not** that the draft passed a quality review.
## First-version limits
Replay supports recorded text/JSON tool results. Tool schemas are frozen, so
this command measures instruction changes, not a migration to new tools. A
changed query, a new research request, or a write/dry-run containing newly
generated text may not have a matching recording. That is a visible mismatch,
not permission to return unrelated old data. No shell command executes,
including commands that are usually read-only or called “dry run.”
This command does not support `--scope`, `--approval`, `--mock-model`, a remote
agent URL, or an additional prompt. Use ordinary `agentuse test` for mocked
flow testing. Judge regression against past human decisions is a separate
operation; replay deliberately captures the writer before the judge intervenes.
## Experimental fixed-input extraction
Full workflow replay still depends on recorded calls. For testing an agent's
output from fixed evidence, the prototype `scripts/extract-fixed-inputs.ts`
asks a model to classify the source session's pre-approval tool results. It
works across tool names and output formats; it does not assume the output is
writing. It does not grade the output or rerun the agent.
The selector distinguishes source evidence, agent-produced material, feedback,
reference instructions, irrelevant records, and uncertain provenance. It sees
call arguments to detect generated material read back through another tool.
Only tool-result text is selectable. Code validates complete classification,
source IDs, exact excerpts, and exclusion of known mutation outputs. Classifier
reasons stay in a separate audit, not the evidence pack.
This is LLM-assisted selection, not a guarantee of semantic purity: arbitrary
tools can return mixed evidence and generated content, and classification can
be wrong. Inspect the audit before treating a pack as a regression fixture.
The model receives broader historical tool data than the eventual input pack;
use an endpoint authorized for that data. No tool executes during extraction.
From the source checkout, build the standalone prototype for Node:
```bash theme={"system"}
bun build scripts/extract-fixed-inputs.ts --target node --packages external --outfile scripts/extract-fixed-inputs.local.mjs
```
Then run from the original agent's project so session storage resolves correctly:
```bash theme={"system"}
node /path/to/agentuse/scripts/extract-fixed-inputs.local.mjs SESSION_ID /path/to/new-output-directory openai:gpt-5.6-sol
```
The output is `input-pack.json`, `selection-audit.json`, `source-records.json`,
and a separate `baseline.json`. The pack contains exact excerpts, hashes, and UTF-16 string offsets;
old assistant output and classifier explanations are not copied into it.
Reference instructions should be supplied fresh to the output-generation step.
Large sessions currently fail an explicit size limit instead of silently
truncating evidence. The public `agentuse test result` command now uses this validated selection primitive and caches evidence for reuse. The standalone script remains useful for inspecting extraction separately.
## Experimental output loop
`scripts/loop-x-output.ts` reuses an existing fixed-input pack for a controlled
X reply experiment. It performs fresh generation, conversation and evidence
checks, then instruction revision only after failure. The canonical brief,
source pack, model and evaluator criteria remain fixed. A passing draft stops
the loop without forced polishing; three failed rounds exhaust the run.
The reviser produces a separate test-guidance paragraph. The next writer sees
that guidance, not the prior drafts, judgments, or historical baseline. Nothing
is written back to production instructions and no publishing tools exist in the
experiment. Automated acceptance is not proof of improvement or permission to
publish. A single example cannot establish a general instruction improvement.
Build from the source checkout and run from the source agent's project:
```bash theme={"system"}
bun build scripts/loop-x-output.ts --target node --packages external --outfile scripts/loop-x-output.local.mjs
node /path/to/agentuse/scripts/loop-x-output.local.mjs /path/to/input-pack.json /path/to/brief.md /path/to/judge.agentuse /path/to/new-output-dir openai:gpt-5.6-sol /path/to/baseline.json
```
The result directory preserves every role's exact request/response, each round's
judgment and instruction revision, frozen inputs, hashes, and the final status.
The optional historical baseline is loaded only after all model calls finish.
This prototype is separate from the public `agentuse test` command.
# Sandbox
Source: https://docs.agentuse.io/guides/sandbox
Run agent commands in an isolated Docker container
The `sandbox` configuration and container execution contract are experimental
and may change without migration. This label is not a security guarantee; use
the isolation boundaries documented below when evaluating untrusted work.
The sandbox runs agent commands inside a Docker container while the **filesystem tool** handles all file I/O on the host. This separation means the agent can execute arbitrary shell commands safely without risking your host system, while file changes flow bidirectionally through bind mounts.
## Quick Start
Add `sandbox: true` and configure filesystem paths:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
sandbox: true
tools:
filesystem:
- path: ${root}
permissions: [read, write]
---
Analyze the project. Run tsc --noEmit to find type errors, then fix them.
```
**Docker** must be installed and running. The image is pulled automatically if needed.
## How Sandbox and Filesystem Work Together
The sandbox **only** provides command execution. All file access is controlled by the filesystem tool:
```mermaid theme={"system"}
flowchart TB
Agent["🤖 Agent"]
FS["Filesystem tool read / write / edit"]
SB["sandbox__exec run shell commands"]
Host["Host Files"]
Container["Docker Container"]
Agent --> FS
Agent --> SB
FS --> Host
SB --> Container
Host <-->|"bind mount (same paths)"| Container
```
* **Filesystem tool** reads/writes files on the host — changes appear inside the container instantly via bind mount
* **`sandbox__exec`** runs commands inside the container — if the mount is read-write, file changes flow back to the host
* **Paths are identical** in host and container (no `/workspace/` alias)
### What Gets Mounted
Each filesystem path from your config is mounted at its **real host path** with the mode derived from its permissions:
```yaml theme={"system"}
tools:
filesystem:
- path: ${root}
permissions: [read] # → mounted read-only
- path: ${root}/src
permissions: [read, write] # → mounted read-write
- path: ${tmpDir}
permissions: [read, write] # → mounted read-write (e.g. /tmp)
```
Glob patterns (e.g. `${root}/**/*.ts`) are skipped — only concrete directories can be mounted. If no filesystem tool is configured, the project root is mounted read-only.
Sandbox refuses to bind-mount `$HOME` (or any ancestor) as the project root. If a project marker like `.git`, `.agentuse`, or `package.json` exists at `$HOME` (common for dotfile repos or per-user config dirs), creation fails with a clear error. Run the agent from inside a real project directory, or declare an explicit `filesystem` mount.
## Configuration
Use `sandbox: true` for defaults (Docker, `node:22-slim`), or provide a config object:
```yaml theme={"system"}
sandbox: true # defaults
sandbox: # full config
provider: docker
image: python:3.12-slim # default: node:22-slim
timeout: 10m # default: 300 seconds
setup: # run after container starts
- pip install pandas numpy
```
| Field | Type | Default | Description |
| - | - | - | - |
| `provider` | `string` | — | Must be `docker` |
| `image` | `string` | `node:22-slim` | Docker image (auto-pulled if missing) |
| `timeout` | `number \| string` | `300` | Max container lifetime. Bare numbers mean seconds; duration strings such as `"10m"` are accepted |
| `setup` | `string \| string[]` | — | Commands to run before agent starts |
| `env` | `string[]` | — | Host env var names to forward into the container |
If any setup command fails (non-zero exit), sandbox creation is aborted.
**Common images:**
* `node:22-slim` — Node.js / TypeScript (default)
* `python:3.12-slim` — Python / data science
* `ubuntu:24.04` — General purpose
* `golang:1.23` / `rust:1.84-slim` — Go / Rust
Need multiple runtimes? Use `setup` to install them (e.g. `apt-get install -y nodejs`).
### Environment Variables
The container starts with a **clean environment** — no host env vars are passed in, even if they are defined in your project's `.env` file. AgentUse loads `.env` into the host process, but the sandbox container does not inherit them.
To forward specific env vars into the container, use the `env` allowlist:
```yaml theme={"system"}
sandbox:
provider: docker
env:
- OPENAI_API_KEY # from .env or shell environment
- DATABASE_URL
```
Only declared vars that exist on the host are forwarded. Unset vars are silently skipped.
## Examples
### TypeScript Code Fix
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
sandbox: true
tools:
filesystem:
- path: ${root}
permissions: [read, write] # write also grants edit
---
You are a code quality agent.
Run tsc --noEmit to find type errors, then fix them and verify.
```
### Python Data Processing
```yaml theme={"system"}
---
model: openai:gpt-5.4-mini
sandbox:
provider: docker
image: python:3.12-slim
setup: pip install pandas matplotlib
tools:
filesystem:
- path: ${root}
permissions: [read, write]
store: true
---
You are a data analysis agent.
Run analysis scripts, save charts to the project, and store key metrics.
```
### Security Scanning (Read-Only)
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
sandbox:
provider: docker
setup: npm install -g snyk
tools:
filesystem:
- path: ${root}
permissions: [read]
store: true
---
You are a security scanning agent.
Run snyk test, identify critical vulnerabilities, and store findings.
```
## Lifecycle
1. **Cleanup** — Remove any orphaned containers from previous runs (crash/force-quit safe)
2. **Pull** — Auto-pull the Docker image if not available locally
3. **Create** — Start container with filesystem paths bind-mounted at real host paths
4. **Setup** — Run `setup` commands sequentially inside the container
5. **Execute** — Agent uses `sandbox__exec` for commands, filesystem tool for file I/O
6. **Teardown** — Container is stopped and removed when the session ends, times out, or is aborted
Need to run AgentUse itself inside Docker? See the self-hosting guide.
# Scheduled Agents
Source: https://docs.agentuse.io/guides/schedule
Run agents on a recurring schedule using cron expressions or intervals
Run agents automatically on a schedule using `agentuse serve`. Configure schedules in agent frontmatter with cron expressions or intervals.
## Quick Start
1. Add a `schedule` config to your agent:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
schedule: "1h"
---
Check the system status and send a summary report.
```
2. Start the server:
```bash theme={"system"}
agentuse serve
```
The server displays scheduled agents on startup:
```
Scheduled (1)
Agent Schedule Next Run
monitor.agentuse 0 * * * * Jan 01, 12:00
```
## Pause or resume a schedule
Pause a declared schedule without editing the agent file:
```bash theme={"system"}
agentuse schedules
agentuse schedules pause agents/daily.agentuse
agentuse schedules resume agents/daily.agentuse
```
The agent's `schedule` frontmatter remains unchanged and visible. Pause state is
stored for the current deployment, so another deployment of the same project can
run the schedule independently. You can use the same controls from the agent
page or the Schedules page in the dashboard. Newly suggested schedules created
through guided project discovery start paused until you test and enable them.
## Schedule Formats
The `schedule` field accepts a single string value. The format is auto-detected:
### Intervals
Simple duration format for recurring tasks:
```yaml theme={"system"}
schedule: "30m"
```
Supported units:
| Unit | Example | Max | Description |
| - | - | - | - |
| `s` | `30s` | 59 | Seconds |
| `m` | `10m` | 59 | Minutes |
| `h` | `2h` | 23 | Hours |
For daily or longer schedules, use cron expressions.
### Cron Expressions
Standard cron syntax for precise control:
```yaml theme={"system"}
schedule: "0 9 * * 1-5" # Weekdays at 9am
```
Common patterns:
| Pattern | Description |
| - | - |
| `0 * * * *` | Every hour |
| `*/15 * * * *` | Every 15 minutes |
| `0 9 * * *` | Daily at 9am |
| `0 0 * * 0` | Weekly on Sunday |
| `0 0 1 * *` | Monthly on the 1st |
| `0 9 * * 1-5` | Weekdays at 9am |
Use [crontab.guru](https://crontab.guru) to build and validate cron expressions.
### Timezone
Cron expressions and intervals are evaluated in the **local timezone of the machine running `agentuse serve`**, not UTC. The times you write are literal wall-clock times for that server. Daylight saving transitions are handled automatically, so `0 9 * * 1-5` stays at 9am local across the year.
To pin a schedule to a specific zone, run the server with `TZ` set (for example `TZ=UTC agentuse serve` or `TZ=America/New_York agentuse serve`).
## Example
A scheduled agent for daily reports:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: Generate daily analytics report
schedule: "0 8 * * 1-5" # Weekdays at 8am
tools:
filesystem:
- path: ${root}/data
permissions: [read]
bash:
commands:
- "curl *"
---
Generate the daily analytics report and save it to reports/daily.md.
```
Use cheaper models like `openrouter:minimax/minimax-m3` for frequent, straightforward tasks (health checks, simple monitoring). Reserve `claude-sonnet-4-6` and `claude-opus-4-8` for complex creative tasks.
## Server Options
See [CLI Commands - agentuse serve](/reference/cli-commands#agentuse-serve) for all server options including port, host, and authentication configuration.
## Monitoring
The server logs each scheduled execution:
```
[12:00:00] Running scheduled agent: monitor.agentuse
[12:00:05] Completed: monitor.agentuse (5.2s)
```
Enable debug mode for detailed logs:
```bash theme={"system"}
agentuse serve --debug
```
## Scheduler Ownership and Recovery
Only one `agentuse serve` process arms schedules for a project. The daemon
records that ownership in `.agentuse/scheduler.lock`; other daemons keep serving
the project but skip its schedules to prevent duplicate side effects.
Lock and filesystem errors fail closed: AgentUse skips schedules rather than
risking two daemons running them. A stale daemon lock is reclaimed
automatically. Reclamation itself uses the short-lived
`.agentuse/scheduler.lock.reclaim` guard. If a process is killed during that
critical section, the guard can be left behind and scheduling stays disabled.
After confirming no daemon is currently reclaiming the lock, remove
`.agentuse/scheduler.lock.reclaim`, then touch an agent file or restart
`agentuse serve`. The warning prints the exact file path to remove.
## Next Steps
Trigger agents via HTTP
Deploy in production
# Self-Hosting
Source: https://docs.agentuse.io/guides/self-hosting
Run AgentUse in Docker for local development or production deployment
## Why Self-Host?
Host on your infrastructure. Your data and API keys never leave your network.
Deploy multiple instances behind a load balancer as demand grows.
Expose agents via HTTP API for integration with other services.
Same container runs identically across machines. Share your setup with teammates.
## Quick Start
```bash theme={"system"}
docker run -d --name agentuse \
-p 12233:12233 \
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
-v $(pwd)/agents:/agents \
ghcr.io/agentuse/agentuse:latest
```
Test it:
```bash theme={"system"}
curl http://localhost:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "/agents/hello.agentuse"}'
```
## Local Development
For local development, mount your credentials and workspace instead of using environment variables:
```bash theme={"system"}
docker run -d --name agentuse-dev \
-p 12233:12233 \
-v ~/.local/share/agentuse:/root/.local/share/agentuse \
-v $(pwd):/workspace \
-w /workspace \
ghcr.io/agentuse/agentuse:latest
```
This gives the container access to your OAuth tokens, API keys, and session logs from `agentuse auth login`.
Run agents via exec:
```bash theme={"system"}
docker exec -it agentuse-dev agentuse run my-agent.agentuse
```
Add `alias agentuse-docker='docker exec -it agentuse-dev agentuse'` to your shell profile for convenience.
OAuth tokens may expire. If you encounter auth errors, run `agentuse auth login` on your host to refresh.
## Configuration
### Environment Variables
| Variable | Description |
| - | - |
| `ANTHROPIC_API_KEY` | Anthropic Claude API key |
| `CLAUDE_CODE_OAUTH_TOKEN` | Claude subscription OAuth token; requires the Claude Code subscription provider plugin |
| `OPENAI_API_KEY` | OpenAI API key |
| `OPENROUTER_API_KEY` | OpenRouter API key |
| `OPENCODE_GO_API_KEY` | OpenCode Go API key |
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_REGION` | Amazon Bedrock (SigV4 auth) |
| `AWS_SESSION_TOKEN` | Optional Bedrock session token (temporary credentials) |
| `AWS_BEARER_TOKEN_BEDROCK` | Amazon Bedrock API key (Bearer auth, alternative to SigV4) |
At least one AI provider authentication is required. `ANTHROPIC_API_KEY` works with the built-in provider. `CLAUDE_CODE_OAUTH_TOKEN` works only when the Claude Code subscription provider plugin is installed in the container or mounted project scope.
### Using an Environment File
```bash theme={"system"}
docker run -d -p 12233:12233 --env-file .env \
-v $(pwd)/agents:/agents \
ghcr.io/agentuse/agentuse:latest
```
### Restarts and Worker Memory
`agentuse serve` runs agents in per-project worker processes, and two behaviours matter when you put it behind `pm2`, `systemd`, or a container supervisor.
**A restart releases workers rather than killing them.** Runs already in flight keep going in the released worker and finish normally; only the daemon is replaced. A released worker still has a hard deadline, by default the longest in-flight run's own timeout plus ten minutes of grace, tunable with `AGENTUSE_RELEASE_BACKSTOP_SECONDS`. Set `AGENTUSE_RELEASE_WORKERS=0` if you want the old kill-on-shutdown behaviour instead.
**Idle workers are recycled once they get heavy.** A fresh worker peaks around 130MB of heap; after it has executed runs, that settles at roughly 350-450MB, which a long-lived daemon would otherwise hold forever. When an idle worker is above `AGENTUSE_WORKER_RECYCLE_MB` (default 300) it is retired through the same release path, so a replacement starts serving immediately. Recycling only happens while the worker is idle, and never within two minutes of it starting. Set `AGENTUSE_WORKER_RECYCLE_MB=0` to disable it.
**After a crash, settle the stragglers.** If the host or the container died outright, sessions can be left marked `running` with no process behind them. `agentuse serve` sweeps these at startup, but only back 30 days:
```bash theme={"system"}
docker exec -it agentuse agentuse sessions reconcile --all --dry-run
docker exec -it agentuse agentuse sessions reconcile --all
```
Runs that are genuinely still executing are never touched. See [CLI Commands](/reference/cli-commands#reconcile-stuck-sessions).
## Including Your Agents
**Volume mount** (best for development):
```bash theme={"system"}
-v $(pwd)/agents:/agents
```
**Bake into image** (best for production):
```dockerfile theme={"system"}
FROM ghcr.io/agentuse/agentuse:latest
COPY ./agents /agents
```
## Docker Compose
```yaml theme={"system"}
# docker-compose.yml
version: '3.8'
services:
agentuse:
image: ghcr.io/agentuse/agentuse:latest
ports:
- "12233:12233"
environment:
- ANTHROPIC_API_KEY
- OPENAI_API_KEY
volumes:
- ./agents:/agents
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:12233/api"]
interval: 30s
timeout: 10s
retries: 3
```
## Extending the Base Image
```dockerfile theme={"system"}
FROM ghcr.io/agentuse/agentuse:latest
RUN apk add --no-cache ffmpeg imagemagick
RUN pip3 install --no-cache-dir pandas numpy requests
RUN npm install -g typescript puppeteer
COPY ./agents /agents
```
### Multi-arch Build
```bash theme={"system"}
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myregistry/agentuse:latest \
--push .
```
## Production Deployment
### Reverse Proxy with nginx
```nginx theme={"system"}
server {
listen 443 ssl;
server_name agents.example.com;
location / {
proxy_pass http://127.0.0.1:12233;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 300s;
}
}
```
Start serve with `--public-url https://agents.example.com` (or set `serve.publicUrl`) so approval links use the public address and a keyless daemon accepts requests for that host.
```nginx theme={"system"}
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location / {
limit_req zone=api burst=20 nodelay;
proxy_pass http://127.0.0.1:12233;
}
```
```bash theme={"system"}
certbot --nginx -d agents.example.com
```
## Troubleshooting
Check logs with `docker logs agentuse`. Common causes: missing API keys, port already in use.
The official image binds to `0.0.0.0` by default. If using a custom image, ensure:
```dockerfile theme={"system"}
ENTRYPOINT ["/usr/local/bin/agentuse", "serve", "-H", "0.0.0.0"]
```
Check the volume mount with `docker exec -it agentuse ls /agents`. Ensure API request paths match container paths.
# Operations Dashboard
Source: https://docs.agentuse.io/guides/serve-dashboard
Monitor runs, approvals, results, metrics, and notifications in the AgentUse serve web app
The dashboard and approval UI are supported product surfaces. The JSON API
response shapes and Web Push delivery contract remain experimental and may
change without migration while those integrations mature.
`agentuse serve` includes an operations dashboard for the agents loaded from
your served projects:
```bash theme={"system"}
agentuse serve
```
Open `http://127.0.0.1:12233`. The Home page streams:
* agents running now, with recent output tickers
* sessions waiting for approval
* failed or verification-failed runs that need review
* recent outcomes and upcoming schedules
* deterministic metrics written through `record_metric`
Pending approvals show one row per agent, with the newest gate on top. Older
asks from the same agent sit under **N older asks**, and a red **blocking N runs**
tag shows how many runs are held up. Gates more than two days old get a
**reject N older** action.
Failed runs from the last 30 days that you have not dismissed are grouped by
blocker and subject. Each group shows its run count, the newest run's own words,
and how the blocker was established.
When the cached npm `latest` version is newer than the installed version, Home
also shows a dismissible update banner. Its copy action uses the package manager
that installed AgentUse. Dismissal is stored in that browser for that version,
so a later release can appear normally.
Mock and test sessions are excluded by default from all of these list-backed
surfaces, and they never fire push notifications, so validating an agent does not
distort the picture of what production is doing. They are still stored in full
and remain inspectable: a mock session's page is reachable by id at any time, and
the sessions list can show them on request.
## Review results
Home's **Results** section groups the metrics recorded by each agent over the
selected time window. Opening an agent row leads to the recent jobs behind
those metrics. Each agent page also has a **Results** tab with that agent's own
metric tiles; opening a tile shows the matching records in the metrics store.
Recent jobs and the Sessions page mark finished runs whose result has not been
opened yet. Opening the run clears that state. Completed, incomplete, and
failed runs remain distinct, so partial work is not presented as a successful
report.
Sessions, Agents, Approvals, Schedules, Stores, and Dashboard preferences remain directly
addressable routes. A session page is the durable record for one run: its
activity, approval gate, tool output, result, metrics, verification verdict,
and follow-up controls stay together.
Press Command+Shift+C on macOS or
Ctrl+Shift+C elsewhere to copy a shareable link
to the current dashboard route. A confirmation appears after the URL is copied.
From a completed, failed, or approval-paused session, **Revise agent file**
starts a visible internal session that diagnoses the run and proposes a
validated change for operator review. An agent that has never run can start the
same workflow from its detail page, using the agent file as the starting
evidence. The agent detail hub keeps the resulting history in its **Revisions**
tab. See [Agent Revisions](/guides/agent-revisions) for apply, request-changes,
discard, stale-source, and restore behavior.
Settings can add an existing project or create a managed one, and can disconnect
a project without deleting its files. For an existing project, guided discovery
scans a sanitized, read-only view, accounts for agents already present, and
proposes evidence-backed recurring work. Agent creation runs as a visible
session, and any proposed schedule starts paused until you test and enable it.
The agent and Schedules pages show declared cron expressions and deployment-local
paused state. Pause or resume a schedule there, or with `agentuse schedules
pause` and `agentuse schedules resume`, without editing agent frontmatter.
Choose **Run with custom** from an agent or session action menu to supply a
one-off instruction, select a different configured model, or do both. Leaving
the model unchanged preserves the model declared by the agent.
Provider setup in Settings supports Anthropic and OpenAI login or API keys,
OpenRouter and OpenCode Go keys, plus custom OpenAI Chat Completions, OpenAI
Responses, and Anthropic Messages endpoints.
## Viewer preferences
Dashboard preferences are local to the current Dashboard. In a browser they are
saved in that browser only; in AgentUse for Mac they are saved in the Dashboard
on that Mac. They do not change agents or server configuration.
* Home sections and metric tiles can be hidden and reordered
* Results can use 1, 7, 14, or 30-day windows
* Metric tiles can render as a number, bars, or line chart
* Agents can use cards, tables, metadata columns, grouping, and filters
* Sessions can use list or feed views and combine status, agent, trigger,
triage, and time-window filters
* Sessions can set a "mock runs" filter to hidden (the default), shown, or only
mock
Preferences are stored in `localStorage` and synchronize between tabs through
browser storage events. Clearing site data resets them.
## Install as a web app
The dashboard ships a manifest, home-screen icons, self-hosted fonts, and a
cache-first service worker.
* **iPhone/iPad:** open the dashboard in Safari, use Share → **Add to Home
Screen**, then launch the installed app
* **Android/desktop Chromium:** use the browser's Install action when offered
The manifest and icons are available before operator authentication so a
token-only session link can still be installed. Cached static assets make repeat
loads fast and tolerate a temporary network outage; live data and actions still
require the daemon.
If a browser deployment leaves a stale cached bundle after an update, open
**Dashboard preferences** and use **Clear cached files & reload**. The service worker activates updates on the next
open, and stale chunk failures trigger one controlled reload automatically.
## Web Push notifications
Notification bells on Approvals, Sessions, and Dashboard preferences control two independent
categories:
* approval requests
* session completions and failures (runs stopped on a person send no "Session failed" push)
The first enable action registers the service worker, requests browser
permission, creates a push subscription, and stores that subscription in the
daemon. Later toggles update only the category preference. Turning off the last
category removes the server record and unsubscribes the browser.
Subscriptions and VAPID keys persist under the AgentUse XDG data directory.
Endpoints reported gone by the push provider are removed automatically. Push
delivery is best-effort; the dashboard and session log remain the source of
truth.
iOS Web Push works only from an installed Home Screen app. A normal Safari tab
shows installation guidance instead of requesting a permission it cannot use.
If permission is denied, AgentUse cannot reopen the browser prompt. Re-enable
notifications in the browser or operating-system site settings, then return to
Dashboard preferences.
## Badges and notification links
Approval pushes carry the current pending count as an app badge. The dashboard
resynchronizes the badge when the approvals list changes or a reviewer decides a
gate, correcting any race between the run and the push.
Notification taps open the associated session:
* a warm installed app focuses an existing matching session window when possible
* a cold iOS launch uses Declarative Web Push navigation and a short-lived
cached target so the app can recover the requested session
* the cached cold-launch target expires after two minutes
## Live updates and recovery
The dashboard uses Server-Sent Events for live session and list updates. When a
mobile tab returns to the foreground it reconnects automatically. An immediate
HTTP status fetch paints a session before the event stream catches up, so a
buffered or remote connection does not leave the page on an indefinite loading
state.
Long-running bash calls publish a bounded recent stdout/stderr tail after about
two seconds. This preview is for people only: it is not added to model context,
is removed when the call settles, and does not replace the final durable output.
## Security and deployment
Local loopback deployments are open by default. Exposed hosts require
`AGENTUSE_API_KEY` unless auth is explicitly disabled. Session capability links
carry a token scoped to one session; operator pages and APIs still require the
operator credential.
The daemon sends `Content-Security-Policy: frame-ancestors 'self'`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy: same-origin`, and `X-Content-Type-Options: nosniff` on its responses.
For client-facing or demo deployments:
```json theme={"system"}
{
"serve": {
"hideAgentSource": true,
"brand": { "name": "Acme Operations" },
"terms": {
"project": "workspace",
"folder": "team|teams"
}
}
}
```
See [Configuration Files](/reference/configuration-files) for these keys,
[Approval Gates](/guides/approval-gates) for review behavior, and
[Self-Hosting](/guides/self-hosting) for reverse-proxy deployment.
# Session logs
Source: https://docs.agentuse.io/guides/session-logs
# Session Logs
AgentUse automatically tracks every agent execution with detailed logs, providing full visibility into what happened during each run.
## Quick Start
```bash theme={"system"}
# List recent sessions
agentuse sessions
# View session details (partial ID match supported)
agentuse sessions show 01JFN8
# Show full tool inputs/outputs
agentuse sessions show 01JFN8 --full
# Export as JSON
agentuse sessions show 01JFN8 --json
```
## What Gets Tracked
Each session captures:
| Category | Data |
| - | - |
| **Session** | Agent name, model, MCP servers, project context, timestamps |
| **Messages** | User prompts, system prompts, token usage, cost, duration |
| **Parts** | Text output, tool calls, reasoning, step boundaries |
| **Tools** | Tool name, input, output, duration, errors |
## CLI Reference
### List Sessions
```bash theme={"system"}
agentuse sessions list [options]
agentuse sessions ls [options]
```
**Options:**
* `-s, --subagents` - Include subagent sessions
* `-n, --limit ` - Limit results (default: 10)
* `-j, --json` - Output as JSON
* `--all` - Show sessions across all projects
* `--project [path]` - Show sessions for a project path; defaults to the current project
* `--no-mock` - Hide mock/test runs. The CLI lists them by default, marked `· mock`
**Example output:**
```
Sessions for current project: /Users/you/project
ID STATUS AGENT DATE
--------------------------------------------------
01JFN8K3M2P1 done daily-reporter Today 14:32
01JFN7XYZAB suspended seo-analyzer Yesterday 09:15
01JFN6DEFGH fail code-reviewer Mon 16:45
```
Session state is stored globally and partitioned by project. The CLI defaults to the current project; use `agentuse sessions list --all` when you are looking for a session but are not sure which project owns it.
### Show Session Details
```bash theme={"system"}
agentuse sessions show [options]
```
**Options:**
* `-f, --full` - Show complete tool input/output (not truncated)
* `-j, --json` - Output as JSON
* `--project [path]` - Search a project path; defaults to the current project
* `--all-search` - Search all projects if not found in the selected project
**Example output:**
```
════════════════════════════════════════════════════════════
SESSION: 01JFN8K3M2P1NRXZW4Y5V6Q7B8
════════════════════════════════════════════════════════════
Agent: daily-reporter
Description: Generate daily motivation quotes
Model: anthropic:claude-sonnet-5
Started: 12/21/2025, 2:32:45 PM
MCP Servers: postgres
Project: /Users/you/project
Working Dir: /Users/you/project
────────────────────────────────────────────────────────────
Task: Generate a daily motivation quote with an interesting fact
Tokens: 1523 (in: 892, out: 631) Duration: 3.2s
Parts: text: 2, tool: 3
Output:
Here's today's motivation quote...
─── ✓ Postgres{query} (SELECT * FROM quotes...) 0.8s ────────
{"rows": [{"id": 1, "quote": "..."}]}
────────────────────────────────────────────────────────────
Generated your daily quote successfully!
```
### Show Storage Path
```bash theme={"system"}
agentuse sessions path
agentuse sessions path --project ../other-project
```
Shows where session data is stored for the current project.
## Subagent Sessions
Use `--subagents` to include subagent sessions in listings:
```bash theme={"system"}
agentuse sessions list --subagents
```
## Use Cases
### Debugging Failed Runs
```bash theme={"system"}
# Find recent failed session
agentuse sessions list | grep -i fail
# View full details with complete tool outputs
agentuse sessions show 01JFN8 --full
```
### Cost Tracking
```bash theme={"system"}
# Export sessions as JSON for analysis
agentuse sessions list --json > sessions.json
# Query costs with jq
cat sessions.json | jq '.[].cost'
```
### Audit Logging
Session logs provide a complete audit trail:
* What prompts were sent
* Which tools were called with what inputs
* What outputs were generated
* Token usage and costs
* Error details and stack traces
## Browse Sessions in the Browser
When `agentuse serve` is running, the same sessions are browsable as web pages:
* `/sessions` lists every run, newest first. Filter the list with `?agent=`,
`?status=running|suspended|completed|error|incomplete` (`incomplete` matches only runs blocked on a person; other incomplete runs are listed under `error`),
`?trigger=scheduled|manual|slack|api`, `?days=`, and
`?mock=include|only`. Mock/test runs are hidden by default; `include` adds
them to the list and `only` shows nothing else. A mock session's detail page
is always reachable by id, filter or not.
* `/sessions/` is the per-session page: the full run log, and when the
session is suspended on an approval gate, the approve / reject / comment and
resume controls.
### Internal agent-revision sessions
A completed, failed, or approval-paused run can start a reviewable agent
revision. The original session remains the launch point and durable history,
with a link to each revision. An agent that has never run can instead start from
its detail page and use the current agent file as evidence. The revision session
links back to its origin when one exists and holds the diagnosis, source
proposal or no-change result, reviewer feedback, apply decision, and restore
action.
The Sessions list and feed label these AgentUse-owned jobs as `internal
revision`, group them under **Internal revisions**, and name them **Revising
*agent***. They are distinct from delegated subagents and automated Judge
sessions. See [Agent Revisions](/guides/agent-revisions) for the full review and
write-safety workflow.
For delegated runs, the parent timeline also surfaces important work from nested
descendants. Reviewer comments appear as timestamped feedback; a child working
on that feedback is labeled `revising`, and its next gate is labeled
`awaiting-approval`. Judge sessions are identified as automated pre-review
attempts so they are not mistaken for human decisions.
The `/agents` page opens each agent's detail hub, where you can inspect source,
recent runs and revisions, and start a run. Schedule rows also link to the agent
detail hub; last-run badges still link to the matching session page.
When the model streams its reasoning, it renders inline in the log as dimmed
"Reasoning" entries (the model's "why", subordinate to the visible answer it
precedes). This is on by default for reasoning-capable OpenAI models; for Claude
it requires opting into extended thinking. See
[model configuration](/guides/model-configuration#provider-options) for the
`openai.reasoningSummary` and `anthropic.thinking` options.
```bash theme={"system"}
agentuse serve
open http://127.0.0.1:12233/sessions
```
If a session is stuck at `running` long after its process is gone, usually after a crashed daemon or a killed container, settle it with [`agentuse sessions reconcile`](/reference/cli-commands#reconcile-stuck-sessions). Runs that are still executing are never touched.
On an exposed host these pages require the API key, or a per-session token on the
session page link. See [Approval Gates](/guides/approval-gates#auth-and-the-session-token).
## Related
* [Session Storage Reference](/reference/session-storage) - Directory structure and data schemas
* [Environment Variables](/reference/environment-variables#storage) - Configure storage location with `AGENTUSE_DATA_DIR`
# Skills
Source: https://docs.agentuse.io/guides/skills
# Skills
Skills are based on the [Agent Skills](https://agentskills.io) open standard, originally developed by Anthropic. AgentUse implements this standard to enable portable, reusable instruction modules across different AI agent platforms.
## What Are Skills?
Skills are reusable instruction modules that agents can load on-demand. Think of them as specialized knowledge packages - each skill contains detailed guidance for a specific type of task.
Unlike sub-agents that execute independently, skills provide instructions that the agent follows directly. This makes skills ideal for:
* **Specialized workflows**: Code review checklists, deployment procedures, data analysis patterns
* **Domain expertise**: Writing guidelines, compliance requirements, best practices
* **Reusable templates**: Project scaffolding, documentation formats, testing strategies
* **Cross-agent knowledge**: Share instructions across multiple agents without duplication
## Quick Start
1. Create a skill directory:
```bash theme={"system"}
mkdir -p .agentuse/skills/code-review
```
2. Add a `SKILL.md` file with YAML frontmatter and markdown content:
```yaml theme={"system"}
---
name: code-review
description: Review code for quality, security, and maintainability.
allowed-tools: Read Bash(git:*)
---
```
Then add your skill instructions in markdown below the frontmatter.
3. The skill is automatically available to your agents!
## Skill Locations
Skills are discovered from these directories (in priority order):
| Location | Scope | Purpose |
| - | - | - |
| `.agentuse/skills/` | Project | Project-specific skills |
| `$AGENTUSE_CONFIG_DIR/skills/` | User | Personal skills across projects; defaults to `~/.agentuse/skills/` |
| `.claude/skills/` | Project | Claude ecosystem compatibility |
| `~/.claude/skills/` | User | Claude ecosystem compatibility |
| `~/.agents/skills/` | User | Shared agent skills compatibility |
If duplicate skill names exist, the first discovered skill takes precedence.
Symlinked skill directories and `SKILL.md` files are supported. AgentUse skips
dangling links and resolves directory real paths to prevent circular traversal.
### For AI Coding Assistants
Install the assistant-facing AgentUse skill so Claude Code, Codex, Cursor, and other assistants can drive AgentUse workflows:
```bash theme={"system"}
npx skills add agentuse/agentuse
```
The stub redirects to `agentuse skills get core`, keeping instructions aligned with the installed CLI version. `core` is the entry point: it points on to `runner` (running, listing, sessions, serve, schedules), `creator` (authoring and reviewing `.agentuse` files), and `tester` (validating agents with mock runs), each fetched the same way.
Dashboard creator sessions can read these version-matched builtins directly,
including `core`, `creator`, and `tester`, without shell access. The creator
guide is already included in the authoring context. Builtin guidance is separate
from the installed skill catalog, and reading it grants no execution tools.
## Skill Structure
Each skill lives in its own directory with a `SKILL.md` file:
```
.agentuse/skills/
└── my-skill/ # Directory name should match the skill name
└── SKILL.md # Skill definition file
```
### SKILL.md Format
Skills use markdown with YAML frontmatter:
```yaml theme={"system"}
---
name: my-skill
description: What this skill does
allowed-tools: Read Write
license: MIT
compatibility: ">=0.3.0"
metadata:
author: your-name
version: "1.0.0"
---
```
Below the frontmatter, add your skill instructions in markdown.
### Frontmatter Fields
| Field | Required | Description |
| - | - | - |
| `name` | Yes | Skill identifier (1-64 chars, no spaces or slashes; lowercase with hyphens recommended). See [Name Requirements](#name-requirements) |
| `description` | Yes | What the skill does and when to use it (max 1024 chars) |
| `allowed-tools` | No | Required tools: a space- or comma-separated string, or a YAML list |
| `license` | No | Skill license (e.g., MIT, Apache-2.0) |
| `compatibility` | No | Version requirements or environment notes |
| `metadata` | No | Custom annotations. Values may be strings or nested objects; the runtime never interprets them |
`metadata` is free-form on purpose. AgentUse preserves and surfaces these keys
(`agentuse skills installed list --json`) but never reads them, so a skill shared
with another tool can carry that tool's nested config here without AgentUse
rejecting the skill.
### Name Requirements
A skill name is accepted when it:
* Is 1-64 characters long
* Contains no spaces, forward slashes (`/`), or backslashes (`\`)
When `name` is omitted, the directory name is used, and it must meet the same rules. Agent config (`skills:`) accepts every name discovery accepts, so any discovered skill can be listed or trusted.
For new skills, we recommend:
* Lowercase letters, numbers, and single hyphens (`code-review`, `seo-analyzer`), with an optional `namespace:` prefix (`team:code-review`)
* A `name` that matches the parent directory name
**Recommended:** `code-review`, `seo-analyzer`, `db-migration`
**Accepted for compatibility:** `Code-Review`, `my_skill`, `too--many`, `my.skill`
**Rejected:** `my skill`, `team/review`, a name over 64 characters
## Allowed Tools
The `allowed-tools` field documents which tools your skill needs, for **documentation purposes** and to drive [skill trust](#trusting-a-skill).
Write it as a space-separated string, a comma-separated string, or a YAML list. All three are accepted:
```yaml theme={"system"}
allowed-tools: Read Write Bash(git:*) mcp__github
```
```yaml theme={"system"}
allowed-tools: Bash(agent-browser:*), Bash(npx agent-browser:*)
```
```yaml theme={"system"}
allowed-tools:
- Bash(npm run *)
- Read
```
A `Bash(...)` pattern may contain spaces, so multi-word command prefixes work:
`Bash(git commit *)` and `Bash(npm run *)` are split as single patterns, not on
their internal spaces.
The two trailing-wildcard spellings are equivalent, matching Claude Code's
permission syntax: `Bash(ls:*)` and `Bash(ls *)` mean the same thing. A wildcard
anywhere other than the end (`Bash(git * main)`) is kept as documentation but
grants nothing, because narrowing it to a prefix would grant more than the
pattern describes.
Skills use whatever tools the **agent** has configured. The `allowed-tools` field documents dependencies and provides validation warnings for builtin tools.
### Validation
Only builtin tools are validated against the agent's configuration:
* `Read`, `Write`, `Edit` - checked against `tools.filesystem`
* `Bash`, `Bash(command:*)` - checked against `tools.bash.commands`
### Bash Tool Configuration
| Field | Type | Description |
| - | - | - |
| `commands` | `string[]` | Allowlist of command patterns (supports `*` wildcard) |
| `gated` | `string[]` | Command patterns that require an approved per-action lease |
| `allowedPaths` | `string[]` | Additional directories accessible beyond project root. Supports `~` for home directory. |
| `timeout` | `string` | Command timeout as a suffixed duration such as `"30s"`, `"2m"`, or `"500ms"`; bare numbers are rejected |
Other tool names (like MCP tools) are accepted but not validated - they serve as documentation only.
If validation fails:
* A warning is logged to the console
* The LLM sees a warning message
* The skill still loads (graceful degradation)
## Agent Tool Configuration
Skills run with the **agent's tools**. For a skill to use the tools it documents, the agent must have them configured.
Agents use `skills: auto` by default, even when the field is omitted. This makes installed skills discoverable and lets the model load relevant skills on demand. By default a skill is discovered but granted **nothing**: to run a command a skill documents, it must be in `tools.bash.commands`, or you must trust the skill.
**Trusting a skill grants it the bash commands it declares** in its SKILL.md `allowed-tools`, so you do not have to re-list them. Trust per skill:
```yaml theme={"system"}
skills:
linkedin: trusted
```
or trust every discovered skill (the blunt shortcut, use deliberately):
```yaml theme={"system"}
skills: trusted
```
Trusting a skill is a real trust decision, the same class as installing an editor extension: you are granting a skill you may not have written the commands it asks for. Trust only **grants** (adds the commands so they can run); it never invents gates. Gating stays your explicit call:
* To require approval for a subset of what a skill grants, list that pattern in [`tools.bash.gated`](/guides/approval-gates#gated-commands-mechanical-enforcement). For example, a skill declares `Bash(birdc:*)`, so trusting it grants `birdc *`. If you want `birdc reply *` behind approval, add it to `tools.bash.gated`. Gated-wins precedence gates `birdc reply` while `birdc read` still auto-runs.
```yaml theme={"system"}
skills:
x-personal: trusted # grants birdc *
tools:
bash:
gated:
- "birdc reply *" # ...but reply needs your approval
```
`agentuse doctor` flags granted commands that look irreversible, so you know what to consider gating.
### Preloading skills
List a skill to **preload** it: its instructions are injected before the task starts, so the agent does not have to infer the trigger from the user instruction. Use this when a skill is core to the agent's job.
```yaml theme={"system"}
skills: [linkedin, x-personal]
```
Listing a skill preloads it; **it never hides the others.** Discovery stays on, so every unlisted skill is still loadable on demand. Listing is "these are the skills I use," not "forbid all others."
This reverses pre-`0.16.0` behavior, where `skills: [x]` was an allowlist that silently hid every other skill. Restricting is now an explicit, deliberate act (see below).
To pin the agent to a **closed set** (only the listed skills are visible, everything else is hidden), opt in explicitly with `auto: false`:
```yaml theme={"system"}
skills:
linkedin: # bare = include, no special grant
auto: false # ...and hide every other discovered skill
```
Because hiding skills is the rarer, higher-consequence choice, it is loud (`auto: false`) rather than a silent side effect of listing.
Per-skill map values may be empty or `trusted` (including the object form
`{ trusted: true }`). The pre-0.16 `allow` key has been removed. Grant
individual commands through `tools.bash.commands` instead.
### Skill config forms
| Config | Discovery | Preloaded | Trusted |
| - | - | - | - |
| omitted / `skills: auto` | all | none | none |
| `skills: [linkedin]` | all | linkedin | none |
| `skills: { linkedin: trusted }` | all | linkedin | linkedin |
| `skills: { linkedin:, auto: false }` | **only linkedin** | linkedin | none |
| `skills: trusted` | all | none | all |
To inspect a skill's grants:
```bash theme={"system"}
agentuse doctor path/to/agent.agentuse
agentuse doctor path/to/agent.agentuse --last-run
```
Doctor also shows command-looking snippets mentioned by the skill. This is advisory: it extracts command names from shell code blocks, inline command snippets, `allowed-tools`, pipes, and command substitutions. AgentUse does not treat the output as a permission manifest.
Add `--last-run` when the agent has already failed or behaved unexpectedly. Doctor will inspect the latest recorded session for that agent and report actual blocked bash commands from runtime, which is more accurate than static skill-doc extraction.
### Example
**Skill** (`code-review/SKILL.md`):
```yaml theme={"system"}
---
name: code-review
description: Review code for quality and security.
allowed-tools: Read Bash(git:*) mcp__github
---
```
**Agent** (`reviewer.agentuse`):
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
tools:
filesystem:
- path: ${root} # Grants access to all files under project root
permissions: [read]
bash:
commands:
- "git *"
allowedPaths: # Optional: directories beyond projectRoot
- ~/workspace/other-repo
- /tmp
mcpServers:
github:
command: npx
args: ["-y", "@anthropic/mcp-server-github"]
env:
GITHUB_TOKEN: ${env:GITHUB_TOKEN}
---
You are a code reviewer. Use the code-review skill to analyze changes.
```
The skill documents needing `Read`, `Bash(git:*)`, and `mcp__github`. The agent provides all three through its `tools` and `mcpServers` configuration.
If a skill's instructions reference tools that the agent hasn't configured, those operations will fail at runtime.
## How Agents Use Skills
Skills are exposed to agents via a special `skill` tool. The agent sees available skills listed in XML format and can load them on demand.
When the agent loads a skill, it receives:
* The skill name and base directory
* Any tool warnings (if required tools are missing)
* The full markdown content with instructions
### Skill File Reader
After loading a skill, agents can read additional files from the skill directory using the `skill_read` tool. This is useful for accessing:
* Helper scripts bundled with the skill
* Data files or templates
* Configuration examples
```
skill_read(skill: "code-review", path: "templates/pr-template.md")
```
The skill must be loaded first before reading files from its directory.
### Skill Directory Variables
When a skill is loaded, AgentUse substitutes these placeholders in the skill's content with the skill's absolute directory path. Use them so bundled scripts and assets resolve regardless of where the skill is installed:
| Placeholder | Purpose |
| - | - |
| `${skillDir}` | Legacy AgentUse placeholder |
| `${SKILL_DIR}` | Cross-agent convention |
| `${CLAUDE_SKILL_DIR}` | Claude ecosystem compatibility |
```markdown theme={"system"}
Run `bash ${SKILL_DIR}/scripts/setup.sh` before generating output.
```
Only the curly-brace form is replaced. Literal `$SKILL_DIR` (no braces) is left untouched so runtime shell expansion still works inside scripts.
## Example Skills
### Git Commit Guidelines
**Frontmatter:**
```yaml theme={"system"}
---
name: commit-guidelines
description: Create well-structured git commits following conventional commit format.
allowed-tools: Bash(git:*)
---
```
**Content:** Include guidance on conventional commit format, commit types (feat, fix, docs, refactor, test, chore), and best practices like keeping subject lines under 72 characters.
### API Documentation Writer
**Frontmatter:**
```yaml theme={"system"}
---
name: api-docs
description: Generate comprehensive API documentation from code.
allowed-tools: Read
---
```
**Content:** Include templates for endpoint documentation (HTTP method, path, parameters, response format, error codes) and function documentation (purpose, parameters, return values, examples).
### Database Migration Checker
**Frontmatter:**
```yaml theme={"system"}
---
name: migration-check
description: Validate database migrations for safety before production.
allowed-tools: Read Bash(psql:*)
---
```
**Content:** Include checklists for backwards compatibility, data safety, performance considerations, and rollback planning.
## Skills vs Sub-agents
| Aspect | Skills | Sub-agents |
| - | - | - |
| **Execution** | Instructions followed by parent agent | Runs as separate agent |
| **Context** | Shared with parent agent | Isolated context |
| **Tools** | Uses parent agent's tools (no own config) | Has own tool configuration |
| **Tool declaration** | `allowed-tools` for documentation/validation | Full `tools` config in agent file |
| **Output** | Integrated into parent's response | Returns result to parent |
| **Use case** | Guidelines, procedures, knowledge | Independent tasks |
Use skills for knowledge and procedures. Use sub-agents for independent task execution.
# Store
Source: https://docs.agentuse.io/guides/store
Persistent data storage for tracking work items across agent runs
The `store` configuration and on-disk item format are experimental and may
change without migration. Discuss feedback in
[GitHub Discussions](https://github.com/agentuse/agentuse/discussions).
## What is the Store?
The store is a local file-based storage system that allows agents to track work items and remember information across multiple runs. It's particularly useful for:
* **Multi-run workflows** - Track progress when agents run on a schedule
* **Multi-agent coordination** - Share state between agents working together
* **Task management** - Track tasks through status workflows
* **Agent memory** - Remember facts, preferences, and context across runs
Stores live at the AgentUse project root:
```text theme={"system"}
/.agentuse/store//items.json
```
When you run `agentuse serve -C path/to/agents`, `-C` is the served scope for agent files. AgentUse still walks upward to find the project root, so agent folders inside the same repository can share the same store.
Under `agentuse test` and any other mock run, every store is re-rooted at `/.agentuse/store-mock/-/`, seeded on first use by copying the real store so the agent still reads realistic data. Nothing a mock run writes reaches production state, including the reserved `metrics` store behind the dashboards. The scratch copy is kept so you can inspect what the run would have written, and swept after 7 days.
When you enable the store, your agent automatically gets tools for creating, reading, updating, deleting, and listing items. Tell the agent what to store and when in your agent file's instructions.
## Configuration
### Isolated Store
Use `store: true` for a store that's private to one agent:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
store: true
---
```
The store is named after the agent (e.g., `myagent` from `myagent.agentuse`).
### Shared Store
Use a string name to share a store across multiple agents:
```yaml theme={"system"}
# manager.agentuse
---
type: manager
store: "my-project"
subagents:
- path: ./writer.agentuse
---
# writer.agentuse
---
store: "my-project" # Same store as manager
---
```
All agents using the same store name can read and write to the same data, enabling coordination without explicit communication.
## Capabilities
When `store` is configured, your agent can:
| Operation | Description |
| - | - |
| **Create** | Add new items with type, title, status, data, and tags |
| **Get** | Retrieve a single item by ID (full data, or only selected `fields`) |
| **Update** | Modify existing items (merges changes, doesn't replace) |
| **Conditional update** | Compare current status, data fields, or `updatedAt` and update only on a match |
| **Claim** | Atomically select and transition one matching item |
| **Delete** | Remove items by ID |
| **List** | Query and search items with filters, full-text search, and projection |
**Keep each item compact.** Store rows are workflow records, not document or
analytics containers. Aim to keep `data` at or below 8 KiB. Normalize repeated
records into separate typed items, and keep large reports or datasets as file
artifacts. Larger items are accepted, but store tools warn because reading and
updating them consumes substantial model context.
## Listing and searching
`store_list` is built to be **token-efficient**: by default it returns lightweight summary rows (id, type, title, status, tags, parent, timestamps) **without the `data` payload**. The agent scans the summaries, then calls `store_get` for the full data of the one item it needs, instead of pulling every payload into context.
It accepts these parameters:
| Parameter | Type | Description |
| - | - | - |
| `type` | string | Filter by item type |
| `status` | string | Filter by status |
| `parentId` | string | Filter by parent item ID |
| `tag` | string | Filter by a single tag |
| `ids` | string\[] | Fetch these specific item IDs in one call (batch get) |
| `where` | object | Exact-match filters on keys **inside** `data`, e.g. `{ "stage": "review" }`. Numbers and booleans also match their string form (`"5"` matches `5`) |
| `q` | string | Case-insensitive substring search across title, type, tags, and `data`. Matching summary rows include a short `match` snippet showing where it hit |
| `includeData` | boolean | Return the full `data` payload of each item (default `false`) |
| `fields` | string\[] | Return only these keys from each item's `data` (ignored when `includeData` is true) |
| `since` | string | Only items updated within this window: a relative span (`"7d"`, `"12h"`, `"30m"`), a bare date (`"2026-03-01"`, read as UTC midnight), or a full ISO timestamp |
| `countOnly` | boolean | Return counts instead of rows (see below) |
| `limit` | number | Maximum number of items to return |
| `offset` | number | Number of items to skip (pagination) |
The response is `{ count, total, items }`:
* `count` is the number of rows returned and `total` is how many items match the filters before `limit`/`offset`, so the agent knows whether more remain.
* Alongside the rows, the response carries a single top-level `dataKeysByType` map listing the `data` keys seen for each item type, so the agent knows what it could request via `fields` or `store_get` without paying for the key list once per row. On a 243-item store, a 40-row listing went from 6,639 tokens to 3,785 this way. When you pass `fields`, the key list is dropped entirely and each row instead reports `missingFields` for any key it doesn't have.
An unparseable `since`, or an impossible calendar date like `2026-02-31`, comes back as a tool error naming the accepted forms rather than being silently ignored.
### Counting
To size a store before reading it, use `countOnly: true`. It returns `total` plus `byType`, `byStatus`, `oldest`, and `newest`, with no rows at all, for around 140 tokens. It respects every filter and ignores `limit`/`offset`, so it always describes the whole matching set.
This matters because `store_list` has **no default limit**: an unfiltered call returns every item and fails loudly against the tool-output cap rather than silently truncating. Ask for the shape first, then ask for rows.
**Keep retrieval cheap.** Size it (`countOnly`), narrow it (`since`, `type`, `status`, `q`), scan the summary rows, then `store_get` the single item you want. Only set `includeData: true` (or list `fields`) when you genuinely need payloads for several items at once. For a known set of IDs, pass `ids` to fetch them in one `store_list` call.
The same projection applies to `store_get`: pass `fields: ["url", "score"]` to return only those keys from a large item instead of the whole payload.
## Atomic coordination
Use `store_claim` for a shared work queue. Selection and transition happen
under one store lock, so two concurrent runs cannot claim the same matching row:
```typescript theme={"system"}
const claim = await tools.store_claim({
type: "job",
status: "ready",
order: "oldest",
update: {
status: "in_progress",
data: { claimedBy: "worker" }
}
});
```
An empty queue returns `{ success: true, claimed: false, item: null }`.
Use `store_update_if` for compare-and-set updates. Conditions can include the
current `status`, exact values inside `data` through `where`, and the prior
`updatedAt` value. A stale condition returns `matched: false` without modifying
the item.
Do not implement claiming as `store_list` followed by `store_update`. Another
run can select the same item between those calls. Code Mode makes control flow
deterministic, but only atomic store primitives make concurrent transitions
atomic.
## Writing Instructions
Guide your agent's store usage through clear SOP instructions. Here are common patterns:
### State Machine
```markdown theme={"system"}
## Workflow
1. Create items with status "pending"
2. When starting work, update to "in_progress"
3. When complete, update to "done"
4. For failures, update to "failed" with error in data
## Progress Check
- List items with status "pending" to find work
- List items with status "in_progress" to check active work
```
### Parent-Child Relationships
```markdown theme={"system"}
## Structure
- Topic (parent)
- Article (child linked to topic)
- Review (child linked to article)
## Finding Related Items
- List articles filtered by parent topic ID
- List reviews filtered by parent article ID
```
### Tagging for Priorities
```markdown theme={"system"}
## Priority Handling
- Tag urgent items with "urgent"
- When checking for work, prioritize items tagged "urgent"
- Use tags like "bug", "feature", "review" for categorization
```
### Agent Memory
```markdown theme={"system"}
## Memory Management
- Store important facts with type "memory"
- Use tags to categorize: "user-preference", "learned-fact", "context"
- Before starting work, list recent memories for relevant context
- When learning something important, store it for future runs
## What to Remember
- User preferences discovered during tasks
- Decisions made and their reasoning
- Facts that will be useful in future runs
- Corrections or feedback received
```
## Storage Location
Stores are saved to:
```
.agentuse/
store/
{storeName}/
items.json # The data
lock # Process lock file
```
Don't edit `items.json` directly while an agent is running. The lock file prevents corruption from concurrent access.
## Example: Content Pipeline
```yaml theme={"system"}
# manager.agentuse
---
type: manager
store: "content"
subagents:
- path: ./researcher.agentuse
- path: ./writer.agentuse
---
## SOP
### Research Phase
1. Delegate to researcher to find topics
2. Store each topic with type "topic" and status "pending"
### Writing Phase
1. List pending topics from the store
2. For each topic, delegate to writer with the topic ID
3. Writer creates an article linked to the topic (as parent)
4. Update topic status to "written"
### Status Workflow
- Topics: pending → in_progress → written
- Articles: draft → review → done
```
## Debugging
### View Store Contents
If you are running `agentuse serve`, open the store browser:
```bash theme={"system"}
http://127.0.0.1:12233/stores
```
Each store has its own table:
```bash theme={"system"}
http://127.0.0.1:12233/stores/my-project
```
Session and approval logs link store tool activity to the matching store table. When AgentUse knows the item ID, the link highlights the changed row:
```bash theme={"system"}
http://127.0.0.1:12233/stores/my-project?highlight=01KQTG63ZQHFH9PP2B17QWMQZP
```
```bash theme={"system"}
# Pretty print store
cat .agentuse/store/my-project/items.json | jq
# Count items by status
cat .agentuse/store/my-project/items.json | jq '.items | group_by(.status) | map({status: .[0].status, count: length})'
```
### Check Lock Status
```bash theme={"system"}
# See who holds the lock
cat .agentuse/store/my-project/lock
# Remove stale lock (only if agent crashed)
rm .agentuse/store/my-project/lock
```
### Reset Store
```bash theme={"system"}
# Clear all items (be careful!)
rm -rf .agentuse/store/my-project
```
## Best Practices
Name your types clearly: "topic", "article", "review" instead of "item1", "item2".
Document valid status values and transitions in your SOP.
Put operation results in the `data` field for later reference.
Periodically delete completed items to keep the store manageable.
## Next Steps
Build orchestrating agents with store integration
Run agents on schedules with persistent state
Coordinate teams sharing a store
# Sub-Agents
Source: https://docs.agentuse.io/guides/subagents
Compose agents that can delegate to other agents
## What are Sub-Agents?
Sub-agents allow you to create modular, reusable agents that can be composed together. A parent agent can delegate specific tasks to specialized sub-agents through tool calls.
Sub-agents are automatically converted to tools that parent agents can call. Each sub-agent uses the parent entry's `maxSteps`, then the leaf agent's own `maxSteps`, then the 100-step default.
## Basic Usage
### Define a Sub-Agent
Create `researcher.agentuse`:
```markdown theme={"system"}
---
model: anthropic:claude-haiku-4-5
---
You are a research specialist. Find accurate, relevant information.
## Task
Research the requested topic and provide comprehensive findings.
```
The agent name is automatically derived from the filename (e.g., `researcher.agentuse` becomes `researcher`).
### Use the Sub-Agent
Create `main.agentuse`:
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./researcher.agentuse
---
You coordinate research tasks using specialized agents.
## Task
When asked for information, use the researcher tool to gather data.
```
Sub-agents are called as tools using their filename (without `.agentuse`). The `researcher.agentuse` becomes available as the `researcher` tool.
## Multiple Sub-Agents
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./agents/researcher.agentuse
- path: ./agents/writer.agentuse
- path: ./agents/editor.agentuse
---
You manage content creation using specialized agents.
## Workflow
1. Use researcher tool to gather information
2. Use writer tool to create initial draft
3. Use editor tool to polish and finalize
```
## Sub-Agent Configuration
You can customize sub-agent behavior:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./researcher.agentuse
name: custom_researcher # Override default name
maxSteps: 25 # Override the default step budget
- path: ./writer.agentuse
maxSteps: 100 # Allow more steps for complex writing
---
```
## Path Resolution
All sub-agent paths are resolved relative to the **parent agent file's directory**, ensuring portability across different execution contexts.
See [Agent Syntax - Subagents](/reference/agent-syntax#subagents) for complete path resolution examples and directory structure recommendations.
## Remote Sub-Agents
Remote sub-agents are **not currently supported**. Sub-agents must be local files accessible via the filesystem.
## Passing Context
Sub-agents accept optional parameters when called as tools:
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./data-processor.agentuse
---
You analyze data using specialized processors.
## Task
When given data:
1. Call data_processor tool with task parameter and context
2. Interpret the results
3. Provide insights
Example: data_processor(task="Analyze sales data", context={"period": "Q4 2023"})
```
### Sub-Agent Tool Schema
Each sub-agent tool accepts:
* `task` (optional string): Additional instructions for the sub-agent
* `context` (optional object): Structured data to pass to the sub-agent
The sub-agent receives its original instructions plus any additional task and context.
## Advanced Patterns
### Conditional Delegation
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./technical-expert.agentuse
- path: ./creative-writer.agentuse
- path: ./data-analyst.agentuse
---
You route requests to appropriate specialists.
## Routing Logic
- Technical questions → call technical_expert tool
- Creative tasks → call creative_writer tool
- Data requests → call data_analyst tool
```
### Recursive Delegation
Sub-agents can declare and invoke their own `subagents`. Each relative path is
resolved from the directory of the file that declares it, so a team can be
organized into reusable folders without depending on the root agent's location.
Delegation is bounded. AgentUse rejects circular dependencies and allows two
sub-agent levels by default. Set `MAX_SUBAGENT_DEPTH` to a positive integer when
a workflow intentionally needs a different limit; declarations beyond the
active limit are skipped with a warning.
```yaml theme={"system"}
# orchestrator.agentuse
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./team-lead.agentuse
---
# team-lead.agentuse
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./developer.agentuse
- path: ./tester.agentuse
---
```
Each sub-agent receives only its own configured tools and declared sub-agent
tools. MCP connections remain isolated to the agent that configured them.
### Parallel Processing
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./analyzer-1.agentuse
- path: ./analyzer-2.agentuse
- path: ./analyzer-3.agentuse
---
You process data in parallel using multiple analyzers.
## Task
Split the data and send parts to different analyzer tools.
Combine their results for comprehensive analysis.
You can call multiple tools in sequence or use them to analyze different aspects of the same data.
```
Sub-agents run sequentially, not in true parallel. The parent agent calls each sub-agent tool one at a time.
## Sub-Agent Communication
### Tool and Resource Inheritance
Sub-agents create their own isolated tool environments:
```yaml theme={"system"}
# parent.agentuse
---
model: anthropic:claude-sonnet-5
mcpServers:
database:
command: "node"
args: ["./database-server.js"] # Relative to parent.agentuse location
subagents:
- path: ./child.agentuse
---
# child.agentuse
---
model: anthropic:claude-haiku-4-5
mcpServers:
# Child defines its own MCP servers
filesystem:
command: "npx"
args: ["@modelcontextprotocol/server-filesystem"]
custom:
command: "../tools/my-server" # Relative to child.agentuse location
---
```
MCP server commands with relative paths are resolved from the agent file's directory, ensuring consistent behavior across different execution contexts.
Each sub-agent manages its own MCP connections and tools. They don't automatically inherit parent tools.
### System Context
All sub-agents receive consistent system context:
* Date and time information
* Autonomous agent behavior prompts
* Model-specific system messages (e.g., "Claude Code" for Anthropic models)
## Best Practices
Each sub-agent should have one clear purpose. This makes them reusable and easier to maintain.
Define clear expectations for what each sub-agent receives and returns.
Parent agents should handle sub-agent failures gracefully.
Use lighter models (like Haiku) for simple sub-agents to reduce costs and latency.
Test sub-agents independently before composing them.
## Example: Customer Support System
```yaml theme={"system"}
# support-system.agentuse
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./agents/ticket-classifier.agentuse
- path: ./agents/knowledge-base.agentuse
- path: ./agents/escalation-handler.agentuse
---
You manage customer support requests.
## Workflow
1. Call ticket_classifier tool to categorize the issue
2. Call knowledge_base tool to find solutions
3. If unresolved, call escalation_handler tool
Each tool returns structured output you can use to make decisions.
```
```yaml theme={"system"}
# ticket-classifier.agentuse
---
model: anthropic:claude-haiku-4-5
---
Classify support tickets into categories:
- Technical issue
- Billing question
- Feature request
- General inquiry
```
## Performance Optimization
### Model Selection
```yaml theme={"system"}
# Optimize model usage
---
model: anthropic:claude-sonnet-5 # Smart coordinator
subagents:
- path: ./simple-task.agentuse # Can use claude-3-5-haiku-latest
- path: ./complex-task.agentuse # Can use anthropic:claude-opus-5
---
```
### Model Override Inheritance
Ordinarily, every agent uses the `model:` declared in its own file. A parent's
configured model does not replace its children's models.
When you explicitly use `--model`, that run-wide override applies to the parent
and every nested sub-agent:
```bash theme={"system"}
agentuse run orchestrator.agentuse --model openai:gpt-5.4-mini
```
Configured aliases keep their complete fallback order and cooldown at every
depth. The resolved override is also stored with the session, so a suspended or
restarted run resumes with the same policy even if the alias configuration has
changed since the run began.
See [CLI Commands - Model Override](/reference/cli-commands#model-override) for complete details on model override behavior and sub-agent inheritance.
### Step Limits
Control sub-agent execution limits:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
subagents:
- path: ./quick-task.agentuse
maxSteps: 10 # Limit for simple tasks
- path: ./complex-task.agentuse
maxSteps: 200 # More steps for complex work
---
```
Default step limit for sub-agents is 50 (compared to 1000 for main agents).
## Debugging Sub-Agents
### Enable Verbose Logging
```bash theme={"system"}
agentuse run main.agentuse --verbose
```
### Trace Execution
```bash theme={"system"}
DEBUG=agent:* agentuse run main.agentuse
```
### Test Sub-Agents Individually
```bash theme={"system"}
# Test sub-agent directly
agentuse run ./agents/researcher.agentuse "test query"
```
## Security Considerations
Sub-agents run with the same system permissions as the parent process. Each sub-agent:
* Creates its own MCP connections with full permissions
* Can access any tools defined in its configuration
* Runs with the same file system and network access
* Has access to environment variables
### Best Practices for Security
* Audit sub-agent configurations carefully
* Use minimal necessary permissions in MCP server configs
* Avoid loading sub-agents from untrusted sources
* Review sub-agent instructions for potentially harmful commands
* Use `allowedTools` in MCP configs to load only the tools an agent needs, or `disallowedTools` to block specific ones
## Next Steps
Learn about remote agent execution
See sub-agent examples
# Testing Agents
Source: https://docs.agentuse.io/guides/testing-agents
Test workflow steps or compare a new result using evidence from a past job
## Choose what to test
| Command | Question | What runs |
| - | - | - |
| `agentuse test workflow ` | Does the agent carry out its steps correctly? | The agent with simulated tool responses and approval decisions. |
| `agentuse test result --session ` | What result do updated instructions produce from the same evidence? | Fresh generation from saved source evidence, without workflow tools. |
Run `agentuse test --help` to see both choices. Put options after `workflow`
or `result`. Both commands use real model calls and can incur provider costs.
## Compare a result from a past job
```bash theme={"system"}
agentuse test result reply.agentuse --session
agentuse test result reply.agentuse --session --judge quality.agentuse
```
On first use, a selector model extracts external evidence from the original
session before its first approval gate. Exact excerpts and a selection audit
are saved under `/.agentuse/test-evidence/`. Later tests of that
source reuse the selection, even after you edit the instructions or change the
writer model. `--selector-model ` chooses the extractor on first use;
otherwise it uses the agent model. It does not replace already saved evidence.
The writer receives current agent instructions, explicit preloaded skills,
applicable learnings, the original additional prompt, and the selected evidence.
Explicit read-only file grants are loaded as current references and their hashes
appear in the report. Directory and wildcard grants are not expanded into fresh
references. A changed reference can change the result even with fixed evidence.
Relative dates use the original session date. The original output and human
feedback stay out of the writer and judge context and appear only in the report.
This tests the deliverable, not research, delegation, tool behavior, approval,
or publishing. No workflow tool or Code Mode executes. If required evidence or
capabilities are missing, the writer should report `incomplete`. Model-assisted
selection can make mistakes; inspect the saved audit before relying on a test.
Sources must be real sessions that have finished or reached approval and contain
recorded tool evidence. Unsupported/media-only evidence, invalid selections,
and inputs exceeding the context budget fail explicitly without truncation.
`--judge ` supplies quality criteria from a separate agent. Its
current explicit skills, learnings and read-only file references are available,
but it has no tools. It evaluates the new result against the task and evidence;
a pass is not a claim of improvement over the original. Use `--model` to change
the writer model; the judge uses its own configured model.
| Status | Meaning | Exit code |
| - | - | - |
| `generated` | A new result is available; no quality verdict | 0 |
| `passed` | The judge accepted the new result against its criteria | 0 |
| `failed` | The judge rejected it | 1 |
| `incomplete` | The writer could not produce the deliverable | 1 |
| `error` | Extraction, generation, validation, or judging failed | 1 |
`--json` emits the structured report. The printed report path contains the
comparison, evidence provenance, current reference hashes, and any judgment.
Each invocation creates a test session excluded from operational views; it
cannot be resumed as a live run. `--timeout` bounds selection, generation and
judging together. `-C` and `--env-file` work as on `run`.
## Test workflow steps
An agent that sends email, pushes commits, posts to Slack, or deletes rows is
hard to debug by running it. The first real run is also the first irreversible
one, and reading the agent file only tells you what you wrote, not what the model
does with it.
`agentuse test workflow` closes that gap. It runs the agent all the way through, on its
own model, with its own instructions and its own tools, but fabricates the side
effects instead of performing them. You get a full session log of a complete run
with simulated external tool responses and isolated store writes by default.
## Run a workflow test
```bash theme={"system"}
agentuse test workflow my-agent.agentuse
agentuse test workflow my-agent.agentuse "focus on the March invoices"
```
It takes the same run options you already know (`--quiet`, `--debug`, `--no-tty`,
`--compact`, `--timeout`, `-C`, `--env-file`, `-m/--model`, `--json`) plus the workflow options below.
### A Mock Model Is Required
Mock mode fires an LLM call for **every** tool result, so it needs a model it can
reach:
```bash theme={"system"}
agentuse test workflow my-agent.agentuse --mock-model anthropic:claude-haiku-4-5
```
Set it once instead of per run via `AGENTUSE_MOCK_MODEL` in your shell,
`~/.agentuse/.env`, or the [`env` block of
`~/.agentuse/config.json`](/reference/configuration-files#global-env-defaults).
The flag wins over all of them.
**Use the lowest-end model you can reach.** Mocking is not a reasoning task:
the model only has to fabricate a plausible result for a tool given its name
and arguments. Your agent's *actual* reasoning still runs on its own model,
untouched. Deliberately not defaulted to the agent's own model, because running
one mock call per tool result on a premium, rate-limited token produced opaque
`429`s.
## Choose which tools to simulate
New `test workflow` invocations default to **all**: external tool results are
simulated. `--scope gated` explicitly simulates only matching gated bash
commands; other tools execute for real. Approval decisions are simulated in both
modes, and stores are isolated.
```bash theme={"system"}
agentuse test workflow my-agent.agentuse --scope all
agentuse test workflow my-agent.agentuse --scope gated
```
Gated scope only covers gated **bash**. An effectful MCP tool or a channel post
still runs for real, so pair it with a scratch copy of the project when the
agent writes through those. And a fabricated command changes nothing on disk:
a later real command that checks its effect (`git log` after a fabricated
`git push`) sees the unchanged state.
An agent with no `tools.bash.gated` patterns run under gated scope gets a
warning: nothing is mocked, everything runs real, with gates still auto-resolved.
## Approval Gates, Unattended
A test run must finish without a human, so the gate resolves deterministically
instead of suspending. No model plays the reviewer.
```bash theme={"system"}
agentuse test workflow my-agent.agentuse --approval approve # default
agentuse test workflow my-agent.agentuse --approval reject
agentuse test workflow my-agent.agentuse --approval comment:"tighten the subject line"
```
| Decision | What it exercises |
| - | - |
| `approve` | The happy path. Grants the [gated-command lease](/guides/approval-gates) from the gate's `changes[]` exactly like a real reviewer, so `tools.bash.gated` flows complete end to end. On a pick gate it takes the recommended option, else the first |
| `reject` | The cleanup branch. The gate seals and the run ends there |
| `comment:` | The revise-and-re-gate branch, with `` as reviewer feedback |
The comment applies to the **first** gate only; the re-gate that follows is
approved, so the run exercises the revision path and still finishes. Repeating
it on every gate would loop an obedient agent until it gave up.
## What Is Isolated
* **Stores.** Every store, including the reserved `metrics` store behind the
dashboards, is re-rooted at `/.agentuse/store-mock/-/`.
Reads are seeded by copying the real store, so the agent still sees realistic
data; writes land in the scratch copy, which is kept for inspection and swept
after 7 days. See [the store guide](/guides/store).
* **Operational views.** Mock sessions are excluded by default from the serve
home dashboard, agent health, and the sessions list, and they never fire push
notifications, so a test loop does not buzz anyone's phone or distort the
picture of production.
## The Closed Loop
Testing is meant to be iterated, not performed once:
1. Edit the agent file.
2. `agentuse test workflow my-agent.agentuse`.
3. Read the session log: what the agent actually did, in order, with what
arguments.
4. Repeat.
```bash theme={"system"}
agentuse test workflow my-agent.agentuse
agentuse sessions show --full
```
In the dashboard, find the run by flipping the sessions list's "mock runs" filter
to `only mock` (API: `?mock=only`). A mock session's detail page is always
reachable by id whatever the filter says, and the CLI marks these runs with a
trailing `· mock` (hide them with `agentuse sessions list --no-mock`).
For a `tools.bash.gated` flow, the log shows the whole gate sequence: the
`await_human` call with its `changes[]`, the deterministic decision, and the
fabricated command result. In the effect WAL, a fabricated gated command has a
`lease-approved` entry but **no** `bash-spawn` entry, which is the audit signal
that it never executed.
## What a Passing Test Does and Doesn't Prove
* **Mock outputs are non-deterministic.** They are LLM-generated, so two runs can
hand the agent different plausible results. That is useful for probing how the
agent copes with variation, and useless as a regression assertion.
* **Mocked approval decisions are deterministic.** The branch you asked for is
the branch you get, every time.
* **MCP servers still connect at startup** for tool discovery. Under full mock,
their tool calls are simulated; gated scope leaves MCP calls live.
* **Gate enforcement is still real.** Mock mode does not relax the permission
model: a gated command the agent tries to run without a lease is still denied,
exactly as in production.
## Lower-Level Plumbing
`agentuse test workflow` is the front door. The same machinery is exposed on `run` for
scripts and unusual cases:
```bash theme={"system"}
agentuse run agent.agentuse --mock --mock-model anthropic:claude-haiku-4-5
```
Note that `run --mock` keeps the approval gate **real**: `await_human` still
suspends, which is useful when you specifically want to verify the agent pauses.
Add `--mock-approval` for the unattended behaviour `agentuse test workflow` defaults to.
See [CLI Commands](/reference/cli-commands#agentuse-test) for the full flag
reference and [Environment Variables](/reference/environment-variables#mock-mode-testing)
for the `AGENTUSE_MOCK_*` equivalents.
If you drive AgentUse from an AI coding assistant, `agentuse skills get tester`
hands it this workflow directly, version-matched to the installed CLI.
## Related
Gate configuration, reviewer flows, and lease enforcement
Reading what a run actually did
How mock runs isolate persistent state
Writing the agent you are about to test
## Compatibility and advanced debugging
`agentuse test ` retains the older adaptive scope: gated when the agent
has gated bash patterns, otherwise all. Existing scripts keep that behavior.
The new `test workflow` command defaults to all even when gated patterns exist.
For an agent file literally named `workflow` or `result`, use an explicit path
such as `./workflow` with the compatibility form.
`agentuse test --replay ` remains an advanced strict
recorded-call debugger. A changed tool argument without a matching recording
stops it. It is not the same as `test result`, which supplies evidence directly.
See [Replay recorded inputs](/guides/replay).
# Verify
Source: https://docs.agentuse.io/guides/verify
Judge the agent's output before it ships, and redo it with the critique on failure
The `verify` configuration, verdict contract, and redo behavior are
experimental and may change without migration. Discuss feedback in
[GitHub Discussions](https://github.com/agentuse/agentuse/discussions).
## What is Verify?
Verify puts a quality gate between your agent's final output and delivery. After the run finishes, a judge evaluates the output against your criteria. If it fails, the judge's critique is injected back into the same session as a revision instruction and the agent **redoes the output**, with all its tool results and completed work still in context, up to `maxRedos` times. Only then does the output ship to channels, a delegating manager, or the CLI.
The redo is a continuation, not a re-run: the agent sees everything it already did (including side effects like sent messages or filed issues), so it revises the deliverable instead of repeating actions.
## Quick Start
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
verify: true # generic rubric: does the output fulfill the task?
---
# Weekly Report Writer
Summarize this week's metrics into a report.
```
Or with your own rubric:
```yaml theme={"system"}
verify: "Every metric cited must come from a tool result; includes a risks section; no filler"
```
## Configuration Options
| Option | Type | Description |
| - | - | - |
| `criteria` | string | Rubric for the built-in judge (one LLM call). Mutually exclusive with `judge`. |
| `judge` | string | Path to a `.agentuse` file to run as the evaluator, relative to this agent file. Mutually exclusive with `criteria`. |
| `at` | `gate` \| `output` \| `both` | Where the judge runs. Defaults to `gate` when the agent has an approval gate, `output` otherwise. |
| `maxRedos` | number | Maximum critique-informed redos before output ships or the gate applies its configured exhaustion behavior (default `1`, max `10`, `0` = judge only). |
| `model` | string | Model for the built-in judge. Defaults to the agent's own model. Invalid with `judge`. |
`verify: true` uses a generic task-fulfillment rubric. `verify: ""` is shorthand for `{ criteria: "" }`.
## Gate Placement (approval agents)
For agents with an [approval gate](/guides/approval-gates), verify defaults to `at: gate`: the judge reviews each `await_human` request **before** it suspends to the human.
* **Fail** → the run does not suspend. The critique returns as a rejection-with-comment tool result, the same protocol as a human rejection, so the agent revises its draft and requests approval again. The human never sees the failed draft.
* **Pass** → the gate suspends to the human as normal.
* **After a human Comment** → the next gate skips pre-review and goes directly back to that reviewer. Their requested revision is authoritative for that review cycle; an automated judge cannot reinterpret or override it. Machine pre-review feedback does not trigger this bypass.
* **Fail-open** → after `maxRedos` pre-review rejections, or on any judge error, the request goes to the human regardless, with the unresolved critique in the session log. The judge protects your attention; it can never deadlock a run or replace your decision. A gate that reaches the human this way records a `skipped` verify marker, so the approval card and `sessions show` say "not judged" and why. [`gateReview: fresh`](#fresh-gate-review) instead opens a feedback-only human gate and keeps approval blocked.
When a gate offers several drafts (a slate keyed by `options` / `changes[].optionId`), the judge returns one verdict per candidate and lists every failing candidate in one pass. A candidate that passed keeps its pass on the next attempt as long as the reviewed content is byte-identical (the visible text, the exact command, and the media URLs): the gate carries it forward, tells the judge not to re-judge it, and skips the judge call entirely when nothing changed. The bounce sent back to the agent names the passing candidates so it leaves them alone. A rejection of the whole request holds even when every candidate passed.
With a [judge agent](#using-a-judge-agent), the attempts on one gate share **one judge session**: the second attempt resumes the first attempt's child session and sends only the revised request plus which candidates changed. The judge keeps its own reasoning about what it already read, and the provider serves the long prefix from cache, so extra redos cost a fraction of the first. The session is dropped whenever the gate suspends, so a human decision always gets a fresh judge, and a resume is declined when the judge history grows past a fixed size or the `judge` file changed.
Otherwise, the judge receives the full approval payload (draft, exact on-approval content, target reference/excerpt, context) plus bounded prior human decisions from the session, so write criteria against what the reviewer would see. Because the check runs before anything posts, this placement is the quality gate; `at: output` is a post-run audit. Gate placement also works for delegated sub-agents: a leaf's gate is judged in the leaf, before the request cascades to the root.
The payload is **all** the built-in judge sees. It runs without tools, so a criterion about a file on disk is really judged against the agent's *account* of that file. A payload that paraphrases its own artifact gets rejected even when the artifact is correct, and a payload that flatters a broken artifact passes silently. When the criteria describe something on disk, use a [judge agent](#using-a-judge-agent) that can open it.
## Using a Judge Agent
When a one-line rubric isn't enough, the evaluation needs its own files, tools, or a stronger model, point `judge` at another agent file:
```yaml theme={"system"}
verify:
judge: ./shared/reply-judge.agentuse
maxRedos: 1
```
The path resolves relative to the agent file that declares it. `judge` and `criteria` are mutually exclusive, and `model` is invalid alongside `judge` (the judge agent declares its own).
**The judge's body is the rubric.** Where the built-in judge gets your `criteria`, an agent judge is handed `Apply the evaluation standard defined in your own instructions.` in that slot, so the standard has to live in the judge agent itself. Everything else it needs, the task and the candidate output, arrives around it.
The judge is otherwise a normal agent: its own frontmatter controls its model, reasoning effort, and tools. That is the point of using one. Grant it read access to the rubric files, exemplars, or the artifact under review, and it evaluates what is actually on disk instead of what the payload claims. It runs as an inspectable child session, so which files it opened and why it decided are visible in the session log, not just the one-line verdict.
It records its decision by calling `submit_verdict`, a tool injected into every judge agent, exactly once:
```json theme={"system"}
{"pass": false, "critique": "The reply restates the target's framing. Add one distinct layer: a concrete example from practice."}
```
The tool call **is** the verdict; a judge should not also write a JSON object in its text. (A trailing JSON object is still parsed as a fallback, which is how the built-in judge reports, but new judge agents should call the tool.) When `pass` is `false`, `critique` is required and must be actionable in one revision, it is injected verbatim into the redo turn. Everything else the judge writes stays in its own reasoning.
Judges conventionally stay read-only (they evaluate, the parent revises), but this is not enforced, a judge that runs your test suite is a legitimate design. Judges cannot suspend on approval gates, so never give a judge agent `approval: true`; a suspended judge counts as a judge error. A nested `verify:` on a judge is ignored.
## What Happens on Failure
1. The verdict and critique are recorded in the session log (visible in the web UI).
2. The critique is injected as a revision instruction: attempt count, criteria, the critique verbatim, and directives (revise, don't argue with the review, completed side effects stand, tools allowed for new information).
3. The agent's revised output is judged again, up to `maxRedos`.
4. If every attempt fails, the **last output still ships**, and the session is marked `verification: failed`, a needs-attention signal for you or a delegating manager, not a crash.
A judge that itself errors (model/auth/parse failure) never blocks the run: the output ships unverified with a visible `error` marker.
## Cost and Behavior Notes
* Each verification is one extra LLM call; each redo is a continuation of the existing session (prompt caching keeps it near generation-only cost). Redo steps count against `maxSteps`.
* On a gate with a judge agent, the judge's own session is resumed across attempts, so raising `maxRedos` on a slate agent is cheaper than the count suggests: later attempts re-read a cached prefix and re-judge only the candidates that changed.
* The built-in judge defaults to the agent's own model so authentication always works; set `model` to use a cheaper judge.
* Verify requires session storage (the default), it is skipped when no session substrate is available, and skipped for runs that declared themselves incomplete via `report_outcome`.
* If a redo hits an approval gate, the run suspends normally; verification resolves at the end of the resumed run.
## Verify vs. Learning
Verify catches a bad output **now**; [Learning](/guides/learning) makes the agent better **next run**. They compose: a verify critique that fixed the output this run is exactly the kind of rule worth promoting into learnings (automatic promotion is planned).
## Fresh gate review
For editorial workflows that require a new reading of every approval request,
opt in with `gateReview: fresh`:
```yaml theme={"system"}
verify:
judge: ./shared/reply-judge.agentuse
gateReview: fresh
maxRedos: 2
```
Each judged gate gets a fresh judge session and all candidates are checked
again. No previous candidate verdict is carried forward, so unchanged wording is
rechecked when the source or evidence changes.
A gate that directly follows a human Comment skips the judge, exactly as in the
default mode: the revision returns straight to the reviewer who asked for it,
with a `skipped` marker saying it was not judged. The judge filters what reaches
the reviewer's first look; it does not second-guess a reviewer who is already
in the loop.
Fresh mode never lets an agent's own unreviewed replacement reach approval. When failed
verdicts or reviewer errors consume the review budget, the current draft returns
to the human in a feedback-only gate with the latest critique. Approval stays
unavailable. The reviewer can comment with guidance to resume the same session,
which returns the revision straight to them, or reject to stop the action. The
current draft, prior human comments, and automated critique remain in the
session rather than being discarded by a terminal failure.
With `maxRedos: 0`, the initial request is still judged once. A failure then
opens the same feedback-only gate. A reviewer error consumes one attempt. An
approval still requires the human's decision after the automated pass.
Without this option, existing incremental review and fail-open behavior remain
unchanged. This setting only affects gate placement, not final-output review.
# Webhooks
Source: https://docs.agentuse.io/guides/webhooks
Trigger agents via HTTP using the serve API
Run agents on-demand via HTTP webhooks using `agentuse serve`. Integrate with external services, CI/CD pipelines, or any system that can make HTTP requests.
## Quick Start
1. Start the daemon:
```bash theme={"system"}
agentuse serve
```
2. Trigger an agent via HTTP:
```bash theme={"system"}
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "assistant.agentuse"}'
```
## Serving Multiple Projects
AgentUse runs one serve daemon at a time. Repeat `-C` on that daemon to serve multiple project roots:
```bash theme={"system"}
agentuse serve -C ./projA -C ./projB
```
Project ids default to directory basenames. Duplicate ids fail startup.
Select a project in the request body:
```bash theme={"system"}
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"project": "projA", "agent": "assistant.agentuse"}'
```
Without `project`, multi-project requests return `400 PROJECT_REQUIRED` unless a default is set:
```bash theme={"system"}
agentuse serve -C ./projA -C ./projB --default projA
```
Explicit `project` fields override the default.
### Global config
You can put serve defaults in `~/.agentuse/config.json`. See [Configuration Files](/reference/configuration-files#global-serve-config) for the schema and CLI override behavior.
### Environment isolation
Each project loads its own `.env` / `.env.local` in its worker process; env vars never mix across projects.
## API Reference
All JSON endpoints live under the `/api/*` prefix. The root paths (`/agents`,
`/sessions`, `/schedules`, `/stores`, `/approvals`) serve the HTML dashboard
pages instead. The per-session page `/sessions/:id` and its action subroutes
carry their own capability auth (session token / API key / local); see
[Approval Gates](/guides/approval-gates#auth-and-the-session-token).
`POST /run`, `POST /resume/:id`, and the `POST /approvals/:id/...` action
endpoints are also still reachable at their original (un-prefixed) paths for
backward compatibility. `GET /approvals/:id` now redirects to `/sessions/:id`.
Prefer the `/api/*` and `/sessions` paths; the legacy aliases will be removed in
a future release.
### GET /api
Returns version, default project, and served projects. (`GET /` serves the HTML
dashboard built from the same data.)
```json theme={"system"}
{
"version": "0.12.0",
"default": "projA",
"projects": [
{ "id": "projA", "path": "/abs/path/to/projA", "agentCount": 3, "scheduleCount": 1 },
{ "id": "projB", "path": "/abs/path/to/projB", "agentCount": 2, "scheduleCount": 0 }
]
}
```
### POST /api/run
Execute an agent and receive the result. (Legacy alias: `POST /run`.)
**Request:**
```json theme={"system"}
{
"agent": "path/to/agent.agentuse",
"project": "projA",
"prompt": "Optional additional instructions",
"model": "anthropic:claude-sonnet-5",
"timeout": 300,
"maxSteps": 100
}
```
| Field | Type | Required | Description |
| - | - | - | - |
| `agent` | string | Yes | Path to agent file (relative to that project's root) |
| `project` | string | Conditional | Required in multi-project mode unless `--default` is set |
| `prompt` | string | No | Additional prompt appended to agent instructions |
| `model` | string | No | Override model in agent file |
| `timeout` | number | No | Max execution time in seconds (default: 300) |
| `maxSteps` | number | No | Max tool call steps |
**Response:**
```json theme={"system"}
{
"success": true,
"result": {
"text": "Agent response",
"finishReason": "end-turn",
"duration": 1234,
"tokens": { "input": 500, "output": 200 },
"toolCalls": 3
}
}
```
**Error Response:**
```json theme={"system"}
{
"success": false,
"error": {
"code": "AGENT_NOT_FOUND",
"message": "Agent file not found: my-agent.agentuse"
}
}
```
| Error Code | HTTP Status | Description |
| - | - | - |
| `AGENT_NOT_FOUND` | 404 | Agent file doesn't exist |
| `PROJECT_NOT_FOUND` | 404 | Unknown project id in multi-project mode |
| `PROJECT_REQUIRED` | 400 | Multi-project request without `project` or `--default` |
| `INVALID_PATH` | 400 | Path outside project root |
| `INVALID_REQUEST` | 400 | Invalid JSON body |
| `MISSING_FIELD` | 400 | Required field missing |
| `TIMEOUT` | 504 | Execution timed out |
| `EXECUTION_ERROR` | 500 | Runtime error |
### GET /api/agents
Lists the agents the daemon loaded as JSON. `path` matches what `POST /api/run`
expects. (The browsable HTML page is at `/agents`.)
For one agent's capability summary and raw source, use
`GET /api/agents/detail?project=&path=`. The path must match an
agent already loaded by that project; the browsable detail hub is at
`/agents//`.
```json theme={"system"}
{
"success": true,
"agents": [
{ "projectId": "projA", "path": "daily.agentuse", "name": "Daily Digest", "model": "anthropic:claude-sonnet-5", "schedule": "0 9 * * *" }
],
"errors": []
}
```
### GET /api/schedules
Lists scheduled agents as JSON, soonest next run first. (The browsable HTML page
is at `/schedules`.)
```json theme={"system"}
{
"success": true,
"schedules": [
{ "projectId": "projA", "agentPath": "daily.agentuse", "expression": "0 9 * * *", "human": "Daily 9am", "enabled": true, "nextRun": "2026-06-03T16:00:00.000Z", "lastRun": null }
]
}
```
From the terminal, `agentuse serve agents` and `agentuse serve schedules` render these as tables. See [CLI Commands](/reference/cli-commands#serve-agents).
### GET /api/sessions
Lists every run (top-level sessions; subagent sessions are excluded) as JSON,
newest first. Filter with `?agent=`, `?trigger=scheduled|manual|slack|api`,
and `?days=` (default \~7 days). The browsable HTML page is at `/sessions`.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions?trigger=scheduled" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
```json theme={"system"}
{
"success": true,
"sessions": [
{
"project": "projA",
"sessionId": "01JFN8K3M2P1",
"agent": { "id": "daily", "name": "Daily Digest" },
"status": "completed",
"trigger": "scheduled",
"createdAt": 1717430400000,
"updatedAt": 1717430412000
}
],
"window": { "days": 7, "createdAfter": 1716825600000 },
"errors": []
}
```
`trigger` records how the run started: `scheduled` (the built-in scheduler),
`api` (`POST /api/run`), `slack`, or `manual` (CLI runs and the default).
### GET /api/sessions/:id
Returns one session including its run-log entries. API-key gated.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions/01JFN8K3M2P1" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
For the human-facing view + approve page, the redirect target, and the session
token, see [Approval Gates](/guides/approval-gates#experimental-session--approval-api).
## Streaming Response
For real-time output, request NDJSON streaming:
```bash theme={"system"}
curl -N -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-H "Accept: application/x-ndjson" \
-d '{"agent": "analyzer.agentuse"}'
```
Each line is a JSON event:
```json theme={"system"}
{"type": "text", "text": "Analyzing..."}
{"type": "tool-call", "name": "read_file", "args": {"path": "data.txt"}}
{"type": "tool-result", "name": "read_file", "result": "..."}
{"type": "text", "text": "Complete!"}
{"type": "finish", "finishReason": "end-turn", "duration": 2345}
```
## Authentication
When exposing the server externally, authentication is required:
```bash theme={"system"}
# Set API key
export AGENTUSE_API_KEY="your-secret-key"
# Start on all interfaces
agentuse serve --host 0.0.0.0
```
Include the key in requests:
```bash theme={"system"}
curl -X POST http://server:12233/api/run \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{"agent": "assistant.agentuse"}'
```
Use `--no-auth` to bypass authentication (dangerous for production).
## Exposing Your Local Server
Access from your devices or team only:
```bash theme={"system"}
brew install tailscale
tailscale up
agentuse serve --public-url https://..ts.net
tailscale serve --bg 12233
```
`agentuse serve` binds `127.0.0.1` by default, so put it behind `tailscale serve` and pass the resulting URL as `--public-url`. Without it, a keyless daemon rejects requests addressed to the tailnet hostname.
Expose to the internet for external webhooks:
```bash theme={"system"}
brew install cloudflared
cloudflared tunnel --url http://localhost:12233
# in another terminal, once the tunnel prints its URL:
AGENTUSE_API_KEY=your-secret-key agentuse serve --public-url https://xxx.trycloudflare.com
```
The tunnel prints a public `https://xxx.trycloudflare.com` URL with automatic HTTPS. Set `AGENTUSE_API_KEY` so the public endpoint is not open, and pass the tunnel URL as `--public-url` so approval links and the host check use it.
## Integration Examples
### GitHub Webhook
Create an agent to handle GitHub events:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: Process GitHub webhook events
tools:
bash:
commands:
- "gh *"
- "git *"
---
Process the incoming GitHub event and take appropriate action.
```
Configure a GitHub webhook to POST to your server:
```
URL: https://your-server.com/api/run
Content-Type: application/json
Body: {"agent": "github-handler.agentuse", "prompt": ""}
```
### Slack Integration
Slack slash commands require a response within 3 seconds and signature verification. Use a workflow tool as middleware:
**With n8n or Make:**
1. Add Slack trigger node (receives slash commands)
2. Add HTTP Request node → POST to `http://server:12233/api/run`
3. Return agent response to Slack
**With Zapier:**
1. Trigger: Slack → New Slash Command
2. Action: Webhooks → POST to AgentUse `/run`
3. Action: Slack → Send Channel Message with result
Direct Slack integration requires handling the 3-second timeout, form-urlencoded parsing, and request signature verification. Workflow tools handle this automatically.
### n8n / Make / Zapier
Use HTTP request nodes to trigger agents:
1. Set URL to `http://your-server:12233/api/run`
2. Method: POST
3. Headers: `Content-Type: application/json`
4. Body:
```json theme={"system"}
{
"agent": "workflow-agent.agentuse",
"prompt": "{{trigger.data}}"
}
```
### Cron Job (External)
Trigger from system cron instead of built-in scheduler:
```bash theme={"system"}
# /etc/cron.d/agent-tasks
0 * * * * curl -s -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "hourly-task.agentuse"}'
```
## Server Configuration
See [CLI Commands - agentuse serve](/reference/cli-commands#agentuse-serve) for all server options including port, host, debug mode, and authentication configuration.
## Production Deployment
For deploying `agentuse serve` in production with reverse proxies (nginx), process management (PM2), and Docker, see [Self-Hosting](/guides/self-hosting#production-deployment).
## Next Steps
Run agents on a cron schedule
Deploy in production
# Installation
Source: https://docs.agentuse.io/installation
Install AgentUse for macOS or from the command line
## macOS Desktop
Download the signed DMG from the
[latest GitHub release](https://github.com/agentuse/agentuse/releases/latest),
open it, and move **AgentUse** to Applications. The app includes the AgentUse
runtime and dashboard, so it does not require Node.js or a separate CLI
installation.
On first launch, Desktop setup offers two choices:
* **Launch AgentUse at login** is selected by default and is applied when you
select **Continue**.
* **Add CLI launcher** optionally creates `~/.local/bin/agentuse` for use in
Terminal. Setup remains available even if you skip it.
After continuing, the app joins the same guided sample and first-agent flow as
the Web UI.
Learn how the menu-bar app, CLI launcher, and login-shell PATH work together.
## Requirements
These requirements apply to command-line installations. The macOS app bundles
its own runtime.
Node.js 22 or later
macOS, Linux, or Windows with WSL
Check your Node.js version before installing:
```bash theme={"system"}
node --version
```
## Install the CLI globally
A global installation gives you the `agentuse` command in every terminal.
```bash theme={"system"}
npm install -g agentuse
agentuse --version
```
```bash theme={"system"}
pnpm install -g agentuse
agentuse --version
```
```bash theme={"system"}
bun add -g agentuse
agentuse --version
```
```bash theme={"system"}
yarn global add agentuse
agentuse --version
```
Create a project, run the built-in sample, and create your first agent.
## Run without installing
Package runners download AgentUse into their cache and run it without adding a
global command:
```bash theme={"system"}
npx agentuse@latest setup
```
```bash theme={"system"}
pnpm dlx agentuse@latest setup
```
```bash theme={"system"}
bunx agentuse@latest setup
```
Use the same runner prefix for later commands. For example:
```bash theme={"system"}
npx agentuse@latest serve
```
Install AgentUse globally if you expect to use it regularly.
## Upgrade
The AgentUse Mac app downloads updates in the background and prompts when they
are ready. Use **Settings → About** for a manual check or to install an update
you deferred. See [AgentUse for Mac](/guides/macos-desktop#updates) for details.
For command-line installations, run the install command again to move to the
latest release:
```bash theme={"system"}
npm install -g agentuse@latest
```
```bash theme={"system"}
pnpm install -g agentuse@latest
```
```bash theme={"system"}
bun add -g agentuse@latest
```
```bash theme={"system"}
yarn global add agentuse@latest
```
Confirm which version your shell resolves:
```bash theme={"system"}
agentuse --version
```
## Uninstall
Removing the CLI does not remove your projects or AgentUse configuration under
`~/.agentuse`.
```bash theme={"system"}
npm uninstall -g agentuse
```
```bash theme={"system"}
pnpm remove -g agentuse
```
```bash theme={"system"}
bun remove -g agentuse
```
```bash theme={"system"}
yarn global remove agentuse
```
## Install from source
Use this path when contributing to AgentUse or testing an unreleased build.
It requires Node.js 22+, Bun, and pnpm.
```bash theme={"system"}
git clone https://github.com/agentuse/agentuse.git
cd agentuse
corepack enable
pnpm install --frozen-lockfile
pnpm build
npm link
agentuse --version
```
`npm link` points the global `agentuse` command at this checkout. Re-run
`pnpm build` after source changes, or use the repository's development scripts
for watch mode.
## Docker
You do not need Docker to use AgentUse. The official image is intended for
self-hosting and containerized execution.
Run the Web UI, webhooks, schedules, and agents in a container.
## Troubleshooting
Confirm that your package manager's global binary directory is on `PATH`:
```bash theme={"system"}
npm prefix -g
pnpm bin -g
bun pm bin -g
```
Restart your terminal after changing `PATH`. You can also use
`npx agentuse@latest --version` without changing your global installation.
AgentUse requires Node.js 22 or later:
```bash theme={"system"}
node --version
```
With [nvm](https://github.com/nvm-sh/nvm), install and select Node.js 22:
```bash theme={"system"}
nvm install 22
nvm use 22
```
Avoid installing with `sudo`. Use a Node.js version manager such as
[nvm](https://github.com/nvm-sh/nvm) or
[Volta](https://volta.sh), then retry the global installation.
Check which executable your shell resolves:
```bash theme={"system"}
command -v agentuse
agentuse --version
```
Remove an older installation made by another package manager, or put the
intended package manager's global binary directory earlier on `PATH`.
Use the terminal setup path on a remote, headless, or SSH environment:
```bash theme={"system"}
agentuse setup --terminal
```
# Introduction
Source: https://docs.agentuse.io/introduction
Own and operate Markdown-defined AI agents on infrastructure you control
## Own the agents doing your company's work
**AgentUse** is an open-source agent runtime. Define agents in Markdown, run them with Claude, OpenAI, or open models on infrastructure you control, and keep every definition as a plain file in your repository.
Let agents work autonomously. Put consequential actions behind human approval.
Run your first agent without installing AgentUse or configuring an API key
Define instructions, models, tools, and runtime behavior in Markdown
Pause consequential actions for human review, then resume the same session
Run AgentUse locally, on a server, in CI, or inside Docker
## Why AgentUse?
Managed agent platforms provide a runtime but make their hosted environment the operational center. Agent frameworks provide flexible libraries but leave you to assemble the application and operations layer.
AgentUse starts with a plain agent file and supplies the runtime around it: the agent loop, tools, durable sessions, schedules, approvals, HTTP endpoints, and an operations dashboard.
Instructions are natural-language Markdown and configuration is readable YAML. Diff, review, version, and adapt agents using the tools you already use for source code.
AgentUse manages tool calls, sessions, schedules, failures, approval waits, artifacts, and results without requiring you to build an SDK application.
Use the same agent file from the command line, a schedule, an HTTP trigger, CI/CD, or Docker. No hosted AgentUse control plane is required.
Add `approval: true` when work should pause for review. A reviewer can approve, reject, or comment, and AgentUse resumes the durable session with that decision.
Your agent definitions, runtime, and operational state stay under your control.
## Key Features
Put model configuration and capabilities in YAML frontmatter, then describe the work in plain language.
Use Anthropic, OpenAI, OpenRouter, OpenCode Go, Amazon Bedrock, or a compatible local endpoint. Override the model at runtime without rewriting the agent.
Use allowlisted filesystem and shell access, built-in runtime tools, reusable skills, subagents, stores, and Model Context Protocol servers.
Trigger agents from the CLI, schedules, HTTP, CI/CD, or Docker. Inspect durable sessions and review consequential actions from the operations dashboard.
## Try It Now
No API key is needed for this hosted example:
```bash theme={"system"}
npx -y agentuse@latest run https://agentuse.io/hello.agentuse
```
## How It Works
An AgentUse agent is a Markdown file with YAML configuration and plain-English instructions:
```markdown theme={"system"}
---
model: anthropic:claude-haiku-4-5
---
You are a helpful assistant.
## Task
Say hello to the user and ask how you can help them today.
```
Save the file as `hello.agentuse` and run:
```bash theme={"system"}
npx -y agentuse@latest run hello.agentuse
```
The filename becomes the default agent id. The same file can later gain tools, a schedule, approval requirements, skills, subagents, or persistent stores without becoming an application project.
## What Can You Build?
* **Operational agents** that monitor systems, prepare reports, and surface work that needs attention
* **Approval-gated agents** that draft, validate, and pause before sending, publishing, deploying, or deleting
* **Repository and CI agents** that inspect changes, run checks, and produce reviewable artifacts
* **MCP-powered agents** that work with databases, APIs, browsers, and business systems
* **Multi-agent systems** that delegate bounded work to specialized child agents
* **Stateful agents** that preserve structured knowledge and metrics across runs
# Quick Start
Source: https://docs.agentuse.io/quickstart
Set up AgentUse and run your first agent
## Choose how to start
### macOS Desktop
Download AgentUse from the
[latest GitHub release](https://github.com/agentuse/agentuse/releases/latest),
move it to Applications, and open it. On the Desktop setup screen, choose
whether AgentUse should launch at login and optionally add its bundled CLI
launcher for Terminal. Select **Continue** to enter the guided setup.
The app includes the runtime, so macOS Desktop users do not need to install
Node.js or AgentUse globally.
### Command line
```bash theme={"system"}
npm install -g agentuse
agentuse --version
```
See [Installation](/installation) for pnpm, Bun, Docker, and development setup options.
Start the guided Web setup:
```bash theme={"system"}
agentuse setup
```
On Apple silicon Macs you can also choose **Mac app**, which opens the download page; the app bundles its own runtime. Otherwise choose **Browser** for the guided setup. AgentUse opens its Web UI and keeps the
server running in your terminal. Both routes now follow the same onboarding
flow.
Keep the suggested name, `my-agents`, to create a dedicated project under
`~/.agentuse/projects/`, or attach an existing project. AgentUse shows the
full path before anything writes an agent file. For an existing project,
the guided flow can scan a sanitized, read-only view and suggest recurring
work grounded in the repository while accounting for agents already there.
Select **Run sample agent** to see a complete session in the dashboard. The
sample uses built-in data, needs no provider credentials, and does not
create an agent file.
In the sample result, select **Create my first agent**. If no provider is
ready, AgentUse opens the same provider setup used in Preferences before
any model call or agent file write.
Describe what the agent should do, choose a creator model from a connected
provider, and select **Create agent**. That model is used only to design and
name a focused agent using AgentUse authoring guidance; it independently
chooses a suitable runtime model from the connected providers. AgentUse
validates the generated source, runtime-model choice, and static safety
guardrails, then performs a separate read-only model review of whether the
declared tools can support the draft's operations. For example, exact parser
diagnostics require a callable parser, not just permission to read files.
Review the draft, request changes if needed, then select **Save agent**.
This capability review does not execute or test the finished agent, which
still needs validation before its first real run. A schedule
proposed by project discovery starts paused until you test and enable it. If
you prefer to work hands-on, use **Copy prompt to coding agent** instead;
the prepared handoff carries your task and keeps the existing validation
workflow as an escape hatch.
When AgentUse detects the new agent, select **Review agent**, review it, and
start its first real run. If detection takes too long, you can copy the
prompt again or check manually without leaving onboarding.
Your coding agent's own login does not authenticate the agents it creates.
Connect the runtime provider in AgentUse onboarding or Preferences. Do not
paste API keys, authorization codes, or OAuth callback URLs into coding-agent
chat.
### Terminal or headless setup
If a browser cannot be opened, use the same setup flow in the terminal:
```bash theme={"system"}
agentuse setup --terminal
```
AgentUse creates and registers the project, prints its full path, and gives you
the exact next steps. The dashboard is optional for this path.
## Create an agent without a coding agent
You do not need Codex, Claude Code, or another coding agent. Complete
`agentuse setup` first, then use the project path shown by setup.
### 1. Configure a runtime provider
```bash theme={"system"}
cd ~/.agentuse/projects/my-agents
agentuse provider list
agentuse provider login
```
Choose a provider in the login prompt, then list its current models:
```bash theme={"system"}
agentuse models
```
### 2. Write one agent file
Create `agents/hello.agentuse` and replace `:` with an exact
model ID from the previous command:
```markdown theme={"system"}
---
model: :
description: Write a friendly greeting
---
Write a short greeting and suggest one useful task you can help with.
```
### 3. Validate and run it
```bash theme={"system"}
agentuse doctor agents/hello.agentuse
agentuse run agents/hello.agentuse
```
To inspect the result later:
```bash theme={"system"}
agentuse sessions
```
## Start AgentUse again
Setup is only required once. Later, start the registered project and Web UI
with:
```bash theme={"system"}
agentuse serve
```
## What's next?
Learn agent syntax and design patterns
Configure providers, credentials, and model defaults
Run an agent automatically
Browse all AgentUse commands
# Agent Syntax Reference
Source: https://docs.agentuse.io/reference/agent-syntax
Complete syntax guide for AgentUse agent files
## File Format
AgentUse agents are markdown files with YAML frontmatter for configuration and plain English instructions.
```markdown theme={"system"}
---
# YAML configuration
name: agent-name
model: provider:model
---
# Markdown content (system prompt)
You are an AI assistant.
## Optional sections
Additional instructions or context.
```
## Frontmatter Reference
### Required Fields
AI model to use for the agent.
Format: `provider:model-name`
Supported providers:
* `anthropic` - Anthropic Claude models
* `openai` - OpenAI GPT models
* `openrouter` - OpenRouter models
* `opencode-go` - OpenCode Go open coding models
* `bedrock` - Amazon Bedrock (Claude, Llama, Mistral, Nova, etc.)
```yaml theme={"system"}
model: anthropic:claude-sonnet-5
model: openai:gpt-5.4-mini
model: openrouter:z-ai/glm-5.3
model: opencode-go:kimi-k2.7-code
model: bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0
```
**Version aliases.** Leave the version off and the agent tracks the newest
model in that line, so it needs no edit when a new release ships:
```yaml theme={"system"}
model: anthropic:claude-sonnet # newest Sonnet
model: openai:gpt-mini # newest small GPT
model: openrouter:x-ai/grok # newest Grok
```
A real model id always wins over an alias, so anything you pin keeps its exact
meaning. See [Version Aliases](/reference/models#version-aliases) for the full
table, and run `agentuse models` to see what each alias resolves to today.
**Named aliases.** `@name` resolves through the `models.aliases` block of your
AgentUse config, which lets many agent files be repointed at once:
```yaml theme={"system"}
model: "@fast"
```
A named alias may be configured with ordered fallback candidates. Fallback is
limited to transient or authentication failures before the current execution
segment receives model output or a tool call. A resumed segment starts on the
concrete model already recorded, then may advance through its persisted
remaining candidates.
**Omitting `model`.** With `models.default` (or `AGENTUSE_MODEL`) configured,
the field is optional and the agent uses that default. Without a default, a
file that omits `model` fails to parse. See
[Configuration Files](/reference/configuration-files#model-defaults-and-aliases).
You can also specify a custom environment variable suffix, which composes with
aliases:
```yaml theme={"system"}
model: anthropic:claude-sonnet-5:dev # Uses ANTHROPIC_API_KEY_DEV
model: anthropic:claude-sonnet:dev # Newest Sonnet, ANTHROPIC_API_KEY_DEV
model: opencode-go:kimi-k2.7-code:dev # Uses OPENCODE_GO_API_KEY_DEV
```
### Optional Fields
Maximum execution time before the agent is terminated. A bare number means
seconds; a suffixed duration string (`"90s"`, `"10m"`, `"1h"`) also works.
Default: 300 (5 minutes)
This prevents runaway agents and provides a safety ceiling for execution time.
Execution receives one wrap-up notice at the next model boundary once the
remaining budget is within the larger of 20% of its effective budget and twice
the slowest model latency observed so far. The agent should return established findings and identify
unfinished work; verification and approval requirements still apply. A running
tool is not interrupted by the notice, so delivery can be later.
The hard deadline remains in force.
A delegated agent that sets its own `timeout` is held to it, constrained by
its parent's remaining budget. One that omits `timeout` inherits the parent's
remaining budget rather than taking a shorter deadline of its own. A child
timeout returns a failed outcome to
the parent; parent cancellation stops descendants. Active time is preserved
across approval suspension and resume, excluding human waiting time. A new
follow-up on an ended session starts a new budget. Historical sessions without
a saved budget begin accounting on their next execution.
Session details show “Wrapping up” after delivery. A returned incomplete
response is labelled “Wrapped up before timeout”; a hard expiry still reads
“Timed out.” A completed task remains “Completed,” with the notice in its
details. Receiving a notice alone never counts as graceful completion.
**Precedence:** CLI `--timeout` flag overrides this value.
```yaml theme={"system"}
timeout: 600 # 10 minutes (bare number = seconds)
timeout: 30m # duration string
```
Choose a timeout appropriate for your agent's expected workload. Simple tasks may complete in seconds, while complex multi-step workflows may need 10-30 minutes.
Maximum number of LLM generation steps (tool call cycles) the agent can take.
Default: 100
This prevents infinite loops and controls cost by limiting the number of LLM calls.
**Precedence:** `MAX_STEPS` environment variable overrides this value.
```yaml theme={"system"}
maxSteps: 50 # Conservative limit for simple tasks
maxSteps: 200 # Higher limit for complex workflows
```
Each step typically involves an LLM call. Higher values increase potential cost if the agent gets stuck in a loop.
Maximum tokens the model may generate in a **single response** (the provider's
`max_tokens`). This is a per-step ceiling, not a run-wide total.
Leave it unset in almost all cases. When unset, first-class Anthropic models
default to their real output limit capped at **32,000**, and other providers use
their own model-max default. Raise it only for an agent that must emit a large
single response or write a big file in one tool call; the value is clamped down
to the model's real output limit when that limit is known.
```yaml theme={"system"}
maxOutputTokens: 64000 # allow a bigger single response / file write
```
This exists because a model id newer than the underlying SDK's model table
(e.g. `claude-sonnet-5`) would otherwise be capped at a tiny 4096 `max_tokens`,
silently truncating normal-length outputs and tool-call arguments. A truncated
response ends the run, so AgentUse sets the cap from its own model registry
instead. Extended thinking (`anthropic.thinking`) computes its own ceiling and
takes precedence over this field.
Tool-call intent phrases. When enabled (the default), every tool schema gains
an optional `intent` parameter: one short phrase from the model stating what
each specific call is trying to achieve (for example, "Running runner tests to
verify the resume fix"). The CLI and the serve session view show the phrase as
the call's activity label, and it is recorded in the session log; the real
tool never sees the parameter (it is stripped before dispatch).
Set `intent: false` to keep tool schemas pristine, for example when a provider
or a third-party MCP server is sensitive to extra parameters, or to save the
few output tokens the phrase costs on every call.
```yaml theme={"system"}
intent: false # disable intent phrases for this agent
```
A brief description of what the agent does.
This description is used in multiple contexts:
* **As subagent tool description**: When this agent is used as a subagent, this becomes the tool description that parent agents see
* **CLI output**: Displayed when running the agent to provide context
* **Plugin events**: Available to plugins for logging or monitoring
* **Documentation**: Self-documenting agents for teams
Best practices:
* Keep it concise (80-120 characters recommended)
* Be action-oriented (describe what the agent does, not what it is)
* Focus on the primary capability or purpose
```yaml theme={"system"}
description: "Reviews code for security vulnerabilities and best practices"
description: "Generates unit tests for JavaScript/TypeScript functions"
description: "Analyzes logs and identifies potential issues"
```
Version identifier for the agent. For developer documentation only - not displayed or used at runtime.
```yaml theme={"system"}
version: "1.0.0"
version: "2024-01-15"
```
Developer notes for setup instructions, requirements, or other documentation. Not displayed at runtime.
```yaml theme={"system"}
notes: |
Setup:
1. Set NEWS_API_KEY environment variable
2. Install jq: brew install jq
```
Free-form annotations for you and your tooling. The framework never
interprets these keys, it only preserves and surfaces them. This is the
sanctioned home for custom keys, which are otherwise stripped from
frontmatter.
```yaml theme={"system"}
metadata:
draft: true
owner: leon
team: growth
```
Metadata is shown by `agentuse agents`: top-level keys render as chips after
the description (a `true` flag prints its bare key, a scalar prints
`key=value`, falsey flags are omitted), and the full object is available in
`agentuse agents --json` under `.metadata` for filtering.
```bash theme={"system"}
# List only draft agents
agentuse agents --json | jq '.agents[] | select(.metadata.draft)'
```
Metadata is an annotation, not runtime input: it is not injected into the
agent's prompt.
Configuration for Model Context Protocol (MCP) servers that provide tools and resources to the agent.
Each server is defined as a key-value pair where the key is the server name and the value is the server configuration.
Array of sub-agent configurations that this agent can delegate tasks to.
Each sub-agent must specify a `path` to the `.agentuse` file, with optional `name` and `maxSteps` parameters.
**Path Resolution**: Subagent paths are resolved relative to the **parent agent file's directory**, not the current working directory. This ensures portability and consistency.
```yaml theme={"system"}
# In /project/agents/main.agentuse
subagents:
- path: ../utils/helper.agentuse # Resolves to /project/utils/helper.agentuse
- path: ./local-agent.agentuse # Resolves to /project/agents/local-agent.agentuse
```
Declare agents whose output this agent consumes, usually through a shared
store. Paths resolve relative to the current agent file, using the same path
rules as `subagents`.
```yaml theme={"system"}
dependsOn:
- ./collect-sources.agentuse
- ./normalize-records.agentuse
```
`dependsOn` is advisory metadata. AgentUse exposes the relationship through
the agents API and relationship graph, but it does **not** serialize runs or
delay schedules. Use compatible schedules or a manager agent when execution
order must be enforced.
A single dependency can use the string shorthand:
```yaml theme={"system"}
dependsOn: ./collect-sources.agentuse
```
Let the agent keep what reviewers tell it and apply the best of it to later
runs. See the [Learning guide](/guides/learning).
`learning: true` applies feedback a reviewer explicitly saved with **Learn
from this comment**, `--remember`, or manual add. An unchecked comment affects
the current run only. Free-form observation capture is opt-in through
`capture.custom` or `capture.agent`.
```yaml theme={"system"}
learning:
capture:
addons: [tool-errors] # typed, structurally-verified channels
custom: | # or: agent: ./capture.agentuse
Only keep instructions about tone and sourcing.
apply: true
max: 20
model: anthropic:claude-haiku-4-5
```
| Key | Type | Description |
| - | - | - |
| `capture` | boolean \| object | Automatic observation configuration. `true` or `{}` enables no automatic channel; human learning uses Learn/`--remember`. Name `addons`, `custom`, or `agent` to opt in. Default `true` |
| `capture.addons` | string\[] | Channels verified structurally in code rather than by prompt. `tool-errors` (failed call → corrected call → confirmed success) is the only entry today. Default `[]` |
| `capture.custom` | string | What is worth keeping, in your own words. Enables free-form observation capture through the built-in evaluator, scoped by this text. Mutually exclusive with `agent` |
| `capture.agent` | string | Path to an `.agentuse` file that replaces the built-in evaluator, relative to this agent file, the same pattern as `verify.judge`. Its candidates are still vetted. Mutually exclusive with `custom` |
| `apply` | boolean | Inject stored, vetted, active learnings into future runs. Default `true` |
| `max` | number | How many learnings this agent keeps, and so how many may reach the model per run. 1-50, default 15. `agentuse doctor` shows what this costs and how many are stored but never injected |
| `model` | string | Helper model used for capture, vetting, and `agentuse learnings tidy`. Defaults to the agent's own model |
`criteria` was removed in v0.18.0 and is a hard parse error:
```
"criteria" was removed — free-form capture is opt-in now. To restore scoped free-form capture, move it to capture: { custom: "..." }
```
Setting both `custom` and `agent` is likewise a parse error.
Boolean `capture: true` still parses, but its meaning narrowed in v0.18.0:
it enables no automatic observation channel. Human feedback becomes durable
only when the reviewer chooses Learn (or uses `--remember`). An agent
carrying it (or `learning: true`) warns once at parse time;
`agentuse doctor` echoes the notice.
`file` and `evaluate` were removed in v0.17.0 and are rejected by name at
parse time, e.g. `Unrecognized key(s) in object: 'file'`. Learnings live in
the AgentUse state directory (`agentuse learnings migrate --all` moves older
ones), and an agent that used `evaluate` to capture without applying should
now set `apply: false`.
Provider-agnostic reasoning effort, the recommended knob. AgentUse normalizes
the requested level to the selected model's supported vocabulary, then uses
the AI SDK or a native provider option to apply it. For example, GPT-5.6 maps
`minimal` to `low`, while modern Claude uses adaptive thinking. One setting
works across Claude and OpenAI without forwarding incompatible values.
```yaml theme={"system"}
model: anthropic:claude-opus-5
reasoning: high # none | minimal | low | medium | high | xhigh | max
```
Use `medium`/`high` for genuine judgment (hard calls under competing
constraints, planning, debugging), `low`/`minimal` for lighter work, omit for
the model default, and `none` to force reasoning off. It is opt-in and bills
reasoning tokens at **output rates**.
Prefer this over the provider-specific `openai.reasoningEffort` /
`anthropic.thinking.budgetTokens` below, which are escape hatches for exact
wire-level control and are honored only when the top-level `reasoning` is unset.
Being top-level, it also avoids the "wrong-level key silently dropped" trap a
misplaced `thinking:` hits.
OpenAI-specific options for GPT-5 and other OpenAI models. `reasoningEffort`
here is the exact-control alternative to the top-level `reasoning` above.
**Supported Options:**
* `reasoningEffort`: Controls thinking effort for reasoning models (`'none'`, `'minimal'`, `'low'`, `'medium'`, `'high'`, `'xhigh'`, `'max'`)
* `reasoningSummary`: Requests a streamed natural-language summary of the model's reasoning (`'auto'` or `'detailed'`), so the reasoning shows up inline in the [session trace](/reference/session-storage). **Defaults to `'auto'` on reasoning-capable models** (the reasoning tokens are billed either way, so the summary is near-free visibility). Non-reasoning models (e.g. `gpt-4o`) omit it.
* `textVerbosity`: Controls response length and detail (`'low'`, `'medium'`, `'high'`)
* `promptCacheKey`: Optional OpenAI prompt-cache routing key. AgentUse sets a stable default per agent when omitted.
* `promptCacheRetention`: Optional OpenAI prompt-cache retention policy (`'in_memory'` or `'24h'`)
* Defaults: when `reasoningEffort`, `textVerbosity`, or `promptCacheRetention` are omitted, AgentUse leaves them unset and uses the OpenAI/AI SDK defaults. When `promptCacheKey` is omitted, AgentUse generates a stable key per agent. `reasoningSummary` defaults to `'auto'` on reasoning-capable models; set it explicitly (or to disable, you currently cannot turn it off via config without leaving a non-reasoning model).
```yaml theme={"system"}
openai:
reasoningEffort: high # More thorough reasoning
reasoningSummary: auto # Surface reasoning in the trace (default on reasoning models)
textVerbosity: low # Concise responses
promptCacheRetention: 24h # Optional extended prompt caching on supported models
```
These options are particularly useful with GPT-5 models to balance response quality, latency, and cost. Some effort levels are model-specific; for example, `xhigh` and `none` are only accepted by OpenAI models that support them. Whether a reasoning summary actually streams depends on `reasoningEffort` and task complexity, the model may emit nothing for trivial tasks.
Anthropic-specific options for Claude models. `thinking.budgetTokens` is the
exact-budget alternative to the top-level `reasoning` above; use it only
when you need to pin an exact token budget.
**Supported Options:**
* `thinking.budgetTokens`: Enables Claude [extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking) with the given token budget (minimum `1024`). When set, Claude streams its reasoning, which appears inline in the [session trace](/reference/session-storage). Honored only when the top-level `reasoning` is unset.
```yaml theme={"system"}
anthropic:
thinking:
budgetTokens: 4096
```
Extended thinking is **off by default** and is an explicit opt-in: enabling it generates new thinking tokens billed at **output rates** (a real cost increase that scales with the budget). AgentUse automatically raises `max_tokens` above the budget to satisfy Anthropic's constraint and reserve room for the answer.
Controls which installed skills are available to the agent.
Default: `auto`
```yaml theme={"system"}
skills: auto
```
`auto` preserves the default behavior: all discovered skills are available for on-demand loading when relevant. A discovered skill is granted nothing until trusted (or its commands are listed in `tools.bash.commands`).
**Trusting a skill grants it the bash commands it declares** in its SKILL.md `allowed-tools`. Trust per skill (recommended) or globally:
```yaml theme={"system"}
skills:
linkedin: trusted # grant just this skill's declared commands
# or: skills: trusted # trust every discovered skill (blunt shortcut)
```
Trust only grants (the commands can run); gating is your explicit call. To require approval for a subset a skill grants (e.g. trust grants `birdc *` but you want `birdc reply *` approved), add that pattern to [`tools.bash.gated`](/guides/approval-gates#gated-commands-mechanical-enforcement); gated-wins precedence gates it while the rest of the family auto-runs. `agentuse doctor` flags granted commands that look irreversible.
To preload a skill before the task starts without trusting it, define it explicitly (grant its commands yourself via `tools.bash.commands`):
```yaml theme={"system"}
skills: [linkedin]
```
Inspect what trust granted with `agentuse doctor `.
You can combine auto discovery with explicit preloads:
```yaml theme={"system"}
skills:
auto: true
linkedin: # preload, but grant no commands
x-personal: trusted
```
Per-skill entries accept only the `trusted` grant. To grant a command without
trusting the skill, list the command explicitly in `tools.bash.commands`.
The removed `allow` key is invalid.
Run `agentuse doctor ` to inspect skill grants.
Doctor can show commands mentioned in the skill docs, but the output is advisory and not a permission manifest.
Add `--last-run` to inspect the latest recorded session and diagnose actual blocked commands from runtime.
Run agent commands inside an isolated Docker container. Requires Docker to be installed and running. Use `sandbox: true` for defaults or provide a config object.
**Fields (when using object form):**
* `provider`: Must be `docker` (required)
* `image`: Docker image to use (default: `node:22-slim`)
* `timeout`: Container timeout: bare number = seconds (default: `300`), or a duration string like `"10m"`
* `setup`: Shell command(s) to run after container starts
* `env`: Host env var names to forward into the container
```yaml theme={"system"}
sandbox:
provider: docker
image: python:3.12-slim
timeout: 600
setup:
- pip install pandas numpy
```
When enabled, the agent receives `sandbox__exec` for running commands in the container. File I/O uses the existing filesystem tool, each filesystem path is mounted at its real host path with per-path ro/rw mode derived from permissions.
This feature is experimental. See the [Sandbox guide](/guides/sandbox) for full documentation.
Schedule for automatic agent execution in serve mode. The format is auto-detected.
**Supported Formats:**
* **Interval**: `5s`, `10m`, `2h` (sub-daily)
* **Cron**: `"0 * * * *"`, `"0 9 * * 1-5"` (daily+)
```yaml theme={"system"}
schedule: "30m" # Every 30 minutes (interval)
schedule: "0 9 * * 1-5" # Weekdays at 9am (cron)
```
Schedules only run when the agent is loaded via `agentuse serve`. Use `agentuse run` for one-off executions.
Add a human approval gate without putting approval instructions in the agent prompt.
When `approval` is present, AgentUse automatically enables the internal `await_human` tool and injects the approval behavior for you. The markdown body should describe the work the agent needs to do; the YAML declares that the work must be reviewed before it is finalized.
```yaml theme={"system"}
approval: true
```
Optional timeout:
```yaml theme={"system"}
approval:
timeout: 24h
```
**Fields:**
* `timeout`: optional suspension timeout such as `24h` or `7d`. A bare number means seconds. Approvals do not expire by default.
Approval requests render best when the agent can provide `summary`, `draft` or `artifact_url`, `context`, and `risk` fields to the internal approval tool.
You can define the approval boundary in the agent instructions. For example:
```md theme={"system"}
You may create local drafts and preview artifacts without approval.
Before scheduling, publishing, sending, deploying, merging, or changing external production state, request approval.
Include the final content, target destination, timing, and risks in the approval request.
```
See [Approval Gates](/guides/approval-gates) for the full setup guide and Approval API examples.
Configure optional external collaboration channels separately from approval policy.
```yaml theme={"system"}
channels: [slack]
```
```yaml theme={"system"}
channels:
slack:
events: [approval, completion, failure]
channel_id: C0123456789
```
**Fields:**
* `channels`: `[slack]` enables Slack with default events and channel env fallback.
* `channels.slack`: `true` or an object to enable Slack.
* `channels.slack.enabled`: optional switch for temporarily disabling Slack.
* `channels.slack.events`: event or list of events. Supported values are `approval`, `completion`, and `failure`. Use `completion`, not `complete` or `completed`.
* `channels.slack.channel_id`: Slack channel id. If omitted, AgentUse uses `SLACK_APPROVAL_CHANNEL`.
See [Channels](/guides/channels) for event semantics, Slack setup, and examples.
## Tools Configuration
Tools are available to agents through:
1. **Built-in Tools** - Sandboxed Code Mode plus filesystem, Bash, and artifact tools with configurable permissions
2. **MCP Servers** - Connect to any Model Context Protocol server
3. **Sub-Agents** - Delegate tasks to other agents
### Built-in Tools
`code_exec` is available automatically and can compose only the tools resolved
for the current agent. Eligible JSON tools are normally called through its
`tools.` catalog, including for a single call, and hidden from the
top-level tool list. Tools that require approval, suspension, subagent
delegation, binary or provider-native result delivery, or outcome submission
stay on the direct path. Bash is available on both paths: Code Mode
can compose structured results from commands in the effective auto-run
allowlist, while commands matching `tools.bash.gated` are rejected there and
must use direct Bash after approval. A transport-sensitive tool may likewise
appear on both paths so its JSON/text result can be composed in Code Mode while
its special result is delivered directly. Configure filesystem, bash, and
artifact capabilities via the `tools` field:
```yaml theme={"system"}
tools:
filesystem:
- path: ${root}
permissions: [read, write] # write also grants edit
bash:
commands: # auto-run allowlist
- "git *"
- "npm *"
gated: # run only after human approval (per-action lease)
- "npm publish *"
artifacts: true # enables artifact_save and artifact_list
metrics: true # enables record_metric
```
`tools.bash.gated` lists commands that need human sign-off: they run only after an approval covering the exact action, and declaring `gated` enables the approval gate automatically. See [Gated commands](/guides/approval-gates#gated-commands-mechanical-enforcement).
See full configuration options for filesystem, bash, and artifact tools
## MCP Servers
### Stdio MCP Configuration
```yaml theme={"system"}
mcpServers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/directory", "--read-only"]
requiredEnvVars: # Variables that must exist
- API_KEY
allowedEnvVars: # Optional variables
- DEBUG_MODE
allowedTools: # Optional: load only these tools
- read_*
- list_directory
disallowedTools: # Optional: tools to exclude
- write_file
- delete_file
toolTimeout: 90 # Optional per-tool-call timeout: bare number = seconds
# (default 60), or a duration string like "2m".
# Env fallback: MCP_TOOL_TIMEOUT (seconds).
```
### HTTP MCP Configuration
```yaml theme={"system"}
mcpServers:
remote_server:
url: https://api.example.com/mcp
sessionId: my-session-123 # Optional session ID
auth: # Optional authentication
type: bearer
token: ${env:API_TOKEN}
headers: # Optional custom headers
X-Custom-Header: custom-value
requiredEnvVars: # Variables that must exist
- API_TOKEN
allowedEnvVars: # Optional variables
- DEBUG_MODE
allowedTools: # Optional: load only these tools
- search
disallowedTools: # Optional: tools to exclude
- dangerous_operation
```
HTTP servers speak the newest MCP protocol (2026-07-28) and fall back to older servers on their own.
### OAuth MCP Servers
Most hosted MCP servers sign you in with OAuth. You don't configure anything for that: give the server's URL and nothing else.
```yaml theme={"system"}
mcpServers:
linear:
url: https://mcp.linear.app/mcp
```
If the server asks for a login, the agent's page in `agentuse serve` shows a **Log in** button next to it, and a run fails that server with a message telling you to log in. You can also log in from the terminal:
```bash theme={"system"}
agentuse mcp login ./triage.agentuse linear
```
AgentUse registers itself with the server. The login is saved per server URL, so every agent that uses the same server shares it, and runs refresh it on their own. A run never waits for a browser. `agentuse mcp status ` shows each server's state, and `agentuse mcp logout ` forgets a login.
A server that refuses the connection but offers no OAuth login wants a key instead: set `auth.token` or an `Authorization` header. Setting either one also turns OAuth off for that server.
Set `auth.type: oauth` only when the server needs a pre-registered client or specific scopes:
```yaml theme={"system"}
auth:
type: oauth
clientId: abc123
clientSecret: ${env:LINEAR_SECRET} # Optional, with clientId
scopes: [read, write] # Optional
```
### Multiple MCP Servers
```yaml theme={"system"}
mcpServers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./data"]
database:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-postgresql"]
requiredEnvVars:
- DATABASE_URL # Must be set in .env or shell
custom:
command: node
args: ["./custom-mcp-server.js"]
allowedEnvVars:
- CUSTOM_CONFIG # Optional configuration
http_api:
url: https://api.example.com/mcp
sessionId: unique-session-id
auth:
type: bearer
token: ${env:API_TOKEN}
requiredEnvVars:
- API_TOKEN
```
The `mcpServers` field uses a map format where each server has a name as the key.
## Sub-Agents
### Sub-Agent Configuration
```yaml theme={"system"}
subagents:
- path: ./agents/researcher.agentuse
name: researcher # Optional custom name
maxSteps: 100 # Optional step limit (default: 100)
- path: ./agents/writer.agentuse
- path: ../shared/validator.agentuse
```
### Remote Sub-Agents
```yaml theme={"system"}
subagents:
- path: https://example.com/agents/helper.agentuse
- path: https://raw.githubusercontent.com/user/repo/main/agent.agentuse
```
Sub-agents can call the main agent or other sub-agents, enabling complex multi-agent workflows.
## Environment Variables in MCP Configuration
**Security by Design**: AgentUse prevents hardcoding secrets in agent files. Use `requiredEnvVars` and `allowedEnvVars` to control which environment variables are passed to MCP servers.
```yaml theme={"system"}
mcpServers:
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
requiredEnvVars:
- GITHUB_TOKEN # Fails if not set
allowedEnvVars:
- GITHUB_DEBUG # Optional, warns if missing
```
See the complete reference for security model, setting environment variables, error messages, and examples.
### MCP Server Configuration Fields
#### Common Fields (All Server Types)
* **`requiredEnvVars`**: Variables that MUST exist. Agent fails if missing.
* **`allowedEnvVars`**: Optional variables to pass through if they exist.
* **`allowedTools`**: When set, only tools matching these names/patterns load (supports wildcards). Tools the server adds later stay off until you list them. Use it when you want a few tools from a large server. Both lists also cover the `list_resources` and `read_resource` tools AgentUse adds for servers with resources.
* **`disallowedTools`**: Tool names/patterns to exclude (supports wildcards). When both are set, `disallowedTools` wins.
#### Stdio Server Fields
* **`command`**: Executable command (required). Relative paths resolve from agent file's directory.
* **`args`**: Command-line arguments (optional)
* **`env`**: Additional environment variables (optional)
#### HTTP Server Fields
* **`url`**: HTTPS URL of the MCP server (required)
* **`sessionId`**: Session identifier (optional)
* **`auth`**: Optional. `token` sends a bearer token (supports `${env:VAR_NAME}`). Without it, a server that asks for an OAuth login gets one (see OAuth MCP Servers); `type: oauth` adds an optional `clientId`, `clientSecret` and `scopes`
* **`headers`**: Custom HTTP headers (optional)
## System Prompt Sections
### Basic Structure
```markdown theme={"system"}
---
name: agent
model: anthropic:claude-sonnet-5
---
You are a helpful assistant.
## Your Role
Detailed description of the agent's role.
## Guidelines
- Guideline 1
- Guideline 2
- Guideline 3
## Task
What the agent should do.
```
### Using Context in Prompts
```markdown theme={"system"}
---
name: personalized
model: anthropic:claude-sonnet-5
---
You are a helpful AI assistant.
## Context
Provide assistance based on the user's specific needs and context.
```
Direct variable interpolation in prompts is not currently supported. Context should be provided through conversation or MCP tools.
### Conditional Sections
```markdown theme={"system"}
---
name: adaptive
model: anthropic:claude-sonnet-5
---
You adapt based on user needs.
## For Technical Users
Provide detailed technical explanations.
## For Non-Technical Users
Use simple language and analogies.
## Task
Determine user level and respond appropriately.
```
## Special Syntax
### Commands
```markdown theme={"system"}
## Available Commands
!help - Show help
!reset - Reset context
!compact - Compact context
!status - Show status
```
### Structured Output
````markdown theme={"system"}
## Output Format
Return responses as JSON:
```json
{
"status": "success",
"data": "...",
"metadata": {}
}
````
````
### Examples in Prompt
```markdown
## Examples
### Example 1
Input: "Translate hello to Spanish"
Output: "Hola"
### Example 2
Input: "What's 2+2?"
Output: "4"
````
## Complete Example
```markdown theme={"system"}
---
model: openai:gpt-5.6
description: "Multi-capability AI assistant with file, GitHub, and research capabilities"
timeout: 900
maxSteps: 150
openai:
reasoningEffort: high
textVerbosity: medium
mcpServers:
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./data", "--read-only"]
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
requiredEnvVars:
- GITHUB_TOKEN # Must be set in .env or shell
allowedEnvVars:
- GITHUB_DEBUG # Optional debug flag
disallowedTools:
- delete_* # Prevent deletion operations
api_server:
url: https://api.example.com/mcp
sessionId: agent-session-123
auth:
type: bearer
token: ${env:API_TOKEN}
requiredEnvVars:
- API_TOKEN
subagents:
- path: ./helpers/researcher.agentuse
name: researcher # Optional custom name
maxSteps: 100 # Optional step limit
- path: ./helpers/writer.agentuse
---
# Multi-Capability Agent
You are an advanced AI assistant with multiple capabilities.
## Your Capabilities
1. **File Access**: Read and write files via the filesystem MCP server
2. **GitHub Access**: Interact with GitHub repositories
3. **Research**: Delegate research tasks to the researcher sub-agent
4. **Writing**: Delegate writing tasks to the writer sub-agent
## Guidelines
- Use the appropriate tool for each task
- Delegate complex tasks to specialized sub-agents
- Handle errors gracefully
- Provide clear, concise responses
## Task
Assist the user with their request using all available capabilities.
```
## Validation Rules
1. **File Extension**: Agent files must use `.agentuse` extension
2. **Model**: Must be a non-empty string (required field)
3. **MCP Server Configuration**:
* Stdio servers: Must have `command` field
* HTTP servers: Must have `url` field with `http://` or `https://` protocol
* Cannot have both `command` and `url` in the same server config
4. **Environment Variables**:
* `requiredEnvVars` and `allowedEnvVars` must be arrays of strings
* Use `${env:VAR_NAME}` syntax to reference environment variables (e.g., in `auth.token`)
5. **Sub-agents**:
* Must be an array of objects
* Each object must have a `path` field (string)
* Optional `name` (string) and `maxSteps` (number) fields
6. **Authentication**: Only `bearer` type is supported for HTTP MCP servers
7. **Tool Restrictions**: `allowedTools` and `disallowedTools` must be arrays of strings (support wildcards)
8. **OpenAI Options**:
* `openai` field is only valid for OpenAI models
* `reasoningEffort` must be one of: `'none'`, `'minimal'`, `'low'`, `'medium'`, `'high'`, `'xhigh'`, `'max'`
* `textVerbosity` must be one of: `'low'`, `'medium'`, `'high'`
* `promptCacheKey` must be a non-empty string of 64 characters or fewer
* `promptCacheRetention` must be one of: `'in_memory'`, `'24h'`
* No other options are allowed under `openai`
## Next Steps
Learn about sub-agents
Configure environment
See it in action
# Built-in Tools
Source: https://docs.agentuse.io/reference/builtin-tools
Configuration reference for Code Mode, filesystem, bash, and artifact tools
AgentUse provides built-in tools for file operations, command execution, and session-linked artifacts. This reference documents their configuration options and path matching behavior.
## Reusable results
Successful direct JSON and text results larger than 10KB are stored outside the
model conversation. The first response contains the original `resultId`,
capabilities, and the first contiguous text page in `content`. `pagination`
contains `page`, `totalPages`, `pageSizeBytes`, `totalBytes`, and `hasMore`.
Follow the returned `next` call unchanged; the last page has `next: null`.
The model can use the read-only `results` tool with `list`, `read`, `grep`, or
`jq`. Direct `read` uses numbered pages; legacy `offset`/`maxBytes` calls still
return byte pages with `nextOffset`. Do not mix the two pagination modes.
Small `jq` responses retain `{values, truncated}`. Oversized responses, or explicit
`page`/`pageSizeBytes` requests, page the serialized `{values, truncated}` response.
The query expression and optional stream `limit` stay in every continuation, using
the same original result ID. Queries execute again on each page, within existing
time/memory/output limits; no derived result is stored. A query's stream-limit
`truncated` flag is separate from page availability and survives reconstruction.
Use deterministic expressions when paging: the stored source is immutable, but
time-dependent expressions such as `now` can change when the query executes again.
Pages are UTF-8-safe text chunks, not necessarily valid JSON individually.
Concatenate `content` before parsing. The default requested size is 16,384 bytes;
JSON escaping and envelope overhead can reduce it. Actual boundaries determine
`totalPages`, and `next` preserves the effective size. Result responses remain
within the configured 20KB wire budget. Exceptionally small budgets or large query
metadata can still fail explicitly when the envelope itself cannot fit.
Structured command results also support `grep` on their searchable output text;
`list` returns reference metadata only.
References are immutable and scoped to one session and agent. Reading one never
replays its tool or side effect. Refresh the original tool only when current
external state is required or an intervening mutation may have invalidated the
stored snapshot.
Provider-native and binary results that use native model-output conversion stay
on their direct delivery path and are not replaced with reusable handles.
## Code Mode
Every normal agent run receives `code_exec` automatically. It executes a
TypeScript function body in an isolated QuickJS-WASM heap so the model can use
ordinary code for loops, filtering, joins, branching, batching, aggregation,
and bounded parallel tool calls.
```typescript theme={"system"}
const result = await tools.store_list({
status: "ready",
includeData: true
});
if (!result.success) throw new Error(result.error);
if (!("items" in result)) throw new Error("Expected item rows");
return {
highPriority: result.items
.filter(item => item.data?.priority === "high")
.map(item => item.id)
};
```
There is no frontmatter switch. The guest receives functions only for tools
already resolved from the agent's `.agentuse` configuration. Eligible JSON
tools are normally hidden from the top-level tool list and called through
`code_exec`, including when the program needs only one tool call. Each nested
call uses the same input object as the direct tool and passes through the
runtime dispatcher, including schema validation, plugin policy, mock isolation,
effect WAL, and session tracing.
Before any nested tool starts, the runtime strictly type-checks the program
against declarations generated from the effective tool schemas. AgentUse-owned
tools can publish trusted output contracts, including the built-in store and Bash tools, so
misspelled inputs, unhandled result variants, and invalid result paths fail
before an effect occurs. External provider and MCP output schemas remain
untrusted and appear as `-> ?`. Inspect an unknown result first, then narrow it
with runtime checks before using its fields in a later program. Completed
JSON-serializable nested calls use the same immutable, same-session result
references, including results too large to read directly into Code Mode:
```typescript theme={"system"}
const recent = await results.list();
const reference = recent[0];
if (reference.capabilities.read) {
const previous = await results.read(reference.resultId);
}
if (reference.kind === "text") {
const matches = await results.grep(reference.resultId, {
pattern: "timeout",
limit: 20,
contextLines: 2,
});
}
if (reference.kind === "json") {
const selected = await results.jq(reference.resultId, {
expression: '.items[] | select(.status == "ready") | { id, status }',
limit: 100,
});
}
```
For a text page of a larger stored payload, supply byte options:
```typescript theme={"system"}
const page = await results.read(reference.resultId, { offset: 0, maxBytes: 6000 });
return { content: page.content, nextOffset: page.nextOffset };
```
Continue from `nextOffset` until it is `null`. Pages preserve UTF-8 characters
and share the direct results tool's response limits. JSON pages need not parse
individually. The one-argument `results.read(resultId)` still returns the original
bounded value. Both forms count toward Code Mode's result-read budget.
Numbered pages are also available through `results.page`:
```typescript theme={"system"}
const page = await results.page({ action: "read", resultId: reference.resultId, page: 1, pageSizeBytes: 6000 });
const more = page.next ? await results.page(page.next) : null;
```
Pass the returned `next` back unchanged; it is `null` on the last page. When numbered page fields are present they take precedence over the legacy `offset` and `maxBytes` options, which are still supported.
Bash returns `{ output, stdout?, stderr?, metadata? }`. Completed processes have
separate `stdout` and `stderr` strings, including empty strings for empty streams.
Parse `stdout` for JSON or other structured command output after checking
`metadata.exitCode`, `timedOut`, `aborted`, and `truncated`. The compatible `output`
field remains combined display text with stderr and runtime diagnostics; it is
not a machine-readable stdout field. Refusals, startup errors, and historical
stored results may lack stream fields. Refusal errors remain JSON text in
`output`; there is no `value` field. Search declarations retain
parameter descriptions and small integer ranges, including `context_lines`
from 0 to 5 for filesystem search.
Preflight reports up to eight diagnostics, bounded to 6,000 characters, with
source locations, TypeScript error codes, and relevant signatures or repair
hints. Annotate helper parameters, such as `function summarize(r: unknown)`,
and narrow unknown values before reading their fields. A failed preflight
executes no nested tools.
Use these references for immediate retries and continued analysis instead of
repeating the same tool call. Refresh the tool when current external state is
required or an intervening mutation may have invalidated the earlier result.
References never cross session or subagent boundaries and do not replay tools
or side effects. `results.grep()` performs bounded, case-insensitive literal
text search by default. Patterns are not regular expressions and characters
such as `$` should not be escaped. `results.jq()` also accepts the legacy
`results.jq(resultId, expression, { limit })` form. It uses real jq syntax and
returns jq's ordered output stream as `{ values, truncated }`. AgentUse runs
bundled jq 1.8.2 WebAssembly in a
resource-limited worker, without a shell, host environment access, jq modules,
or a machine-level jq installation.
Code Mode has no direct filesystem, network, environment, process, package,
shell, or import access. It can invoke only capabilities exposed through the
host tool bridge. This includes Bash commands from the agent's effective
auto-run allowlist; the same command validator, path policy, safe environment,
plugin policy, mocks, cancellation, and effect journal apply on both paths.
Commands matching `tools.bash.gated` are rejected in Code Mode and must use the
direct Bash tool after human approval. Approval gates, outcome tools, internal
creator tools, subagents, and any tool marked as approval-required remain
direct-only. Binary media results also stay on the direct path because the guest
bridge is JSON-only. Programs are bounded by source, memory, stack, computation,
output, nested-call, and concurrency limits. Time awaiting Bash is governed by
the Bash timeout and does not consume the guest computation timeout. The 128 nested
tool-call limit applies to each `code_exec` program, including failed attempts.
A later program receives a fresh allowance; continue unfinished work without
repeating completed effects. Active nested calls (up to 8) and guest memory
(32 MiB) remain shared across programs in the same run. The agent run retains
its own execution timeout and step limits.
Use Code Mode for eligible JSON tools, including a single call, and for an
auto-run Bash command whose output feeds parsing, filtering, branching,
batching, or another tool. Bash remains separately visible for gated commands
and simple standalone process execution. Call other tools directly when they
require suspension, approval, subagent delegation, binary or provider-native
result delivery, or outcome submission. A transport-sensitive tool can appear
on both paths: use its Code Mode form for JSON/text composition and its direct
form only for the special result delivery. Code Mode does not make several
store calls atomic; use `store_claim` or `store_update_if` for concurrent state
transitions.
### Controlled comparison and rollback
Code Mode is part of the runtime, not `.agentuse` syntax. To compare the same
agent with and without deterministic tool composition, run it once normally
and once with the runtime-only kill switch:
```bash theme={"system"}
agentuse run agents/example.agentuse "process the ready jobs"
agentuse run agents/example.agentuse "process the ready jobs" --no-code-mode
```
`--no-code-mode` applies to the whole run tree, including delegated agents.
Use `AGENTUSE_CODE_MODE=0` for test harnesses or to disable Code Mode for every
run launched by a serve daemon. `agentuse serve --no-code-mode` is the CLI
equivalent for one daemon process. These switches are for evaluation,
debugging, and emergency rollback, not permanent per-agent configuration.
## Path Matching Behavior
Filesystem paths and Bash `allowedPaths` use **containment-based** path matching by default:
| Pattern | Mode | Matches |
| - | - | - |
| `${root}` | Containment | All files under project root |
| `${root}/src` | Containment | All files under src directory |
| `${root}/**/*.ts` | Glob | Only `.ts` files anywhere in project |
| `${root}/*.json` | Glob | Only `.json` files in root (not subdirs) |
**Rule:** If the path contains glob characters (`*`, `?`, `[`), it uses glob matching. Otherwise, it uses containment (path = path/\*\*).
## Filesystem Tool
Controls access for Read, Write, and Edit operations. Granting a permission exposes the matching tool to the agent: `read` → `filesystem_read`, `write` → `filesystem_write` (and `filesystem_edit`), `edit` → `filesystem_edit`.
### Configuration
```yaml theme={"system"}
tools:
filesystem:
- path: ${root}
permissions: [read]
- path: ${root}/src
permissions: [read, write] # write also grants edit
- paths:
- ${root}/docs
- ${root}/tests
permissions: [read]
```
### Fields
| Field | Type | Description |
| - | - | - |
| `path` | `string` | Single path or pattern |
| `paths` | `string[]` | Multiple paths or patterns (alternative to `path`) |
| `permissions` | `Permission[]` | Array of allowed operations: `read`, `write`, `edit` |
### Permission Model
The capability hierarchy is `read` \< `edit` \< `write`:
* **`read`**, read file contents.
* **`edit`**, replace strings inside an *existing* file (cannot create new files or overwrite a file wholesale).
* **`write`**, create or overwrite any file. Because this is strictly stronger than `edit`, **granting `write` also grants `edit`** (the agent gets both the write and edit tools).
In practice this means `[read, write]` is all most agents need, the agent can read, do targeted edits, and do full writes. List `edit` on its own only when you want the narrower grant: modify existing files but never create or clobber them.
Prefer `[read, write]` over `[read, write, edit]`, `edit` is redundant alongside `write`. Use `[read, edit]` deliberately when an agent should tweak existing files without the ability to create or overwrite them.
### Reading images and PDFs
`filesystem_read` returns text files with line numbers, but it also reads **images (PNG, JPEG, GIF, WebP) and PDFs**, handing the actual image or document to the model so an agent can reason over a chart, screenshot, or scanned page directly. File type is detected by content (magic bytes), not by extension.
This requires a model whose input modalities include `image`/`pdf` (Claude, GPT-4o, Gemini, and most modern models). On a text-only model, an image/PDF read returns a clear error instead of breaking the run. The same path allowlist applies as for text reads. Size caps: images up to \~5MB, PDFs up to \~32MB; `offset`/`limit` are ignored for media files.
### Path Variables
| Variable | Description |
| - | - |
| `${root}` | Project root directory |
| `${agentDir}` | Directory containing the agent file |
| `${tmpDir}` | System temp directory (or custom if configured) |
| `~` | User's home directory |
### Examples
```yaml theme={"system"}
# Containment mode (recommended for most cases)
filesystem:
- path: ${root}
permissions: [read, write] # read + edit + write
# Restrict to specific subdirectory
filesystem:
- path: ${root}/src
permissions: [read, write]
- path: ${root}/docs
permissions: [read]
# Fine-grained control with glob patterns
filesystem:
- path: ${root}/**/*.ts
permissions: [edit] # edit existing files only, no create/overwrite
- path: ${root}/**/*.md
permissions: [read]
```
### Read Limits
`read_file` returns up to **2000 lines** per call by default (`AGENTUSE_TOOL_MAX_LINES`); pass an explicit `limit` to read more, or an `offset` to page through a larger file. Individual lines longer than **2000 characters** (`AGENTUSE_TOOL_MAX_LINE_LENGTH`) are truncated with a `... (truncated)` suffix. See [Tool Output environment variables](/reference/environment-variables#tool-output) to tune these.
### Edit Operations
The edit tool replaces exact strings rather than rewriting whole files. It uses fuzzy matching to tolerate minor whitespace, indentation, and line-ending differences. **Prefer editing over full writes on large files**, rewriting a large file regenerates its entire contents as output tokens, which is slow and can exhaust a run's time budget.
A single edit replaces one string:
| Parameter | Type | Description |
| - | - | - |
| `file_path` | `string` | Absolute path to the file |
| `old_string` | `string` | Exact string to find and replace |
| `new_string` | `string` | Replacement string |
| `replace_all` | `boolean` | Replace all occurrences (default: `false`, first match only) |
To make several changes in one call, pass an `edits` array instead of the top-level `old_string`/`new_string`:
| Parameter | Type | Description |
| - | - | - |
| `file_path` | `string` | Absolute path to the file |
| `edits` | `Edit[]` | Array of `{ old_string, new_string, replace_all? }` |
Batched edits apply **sequentially** (each to the result of the previous) and are **all-or-nothing**: if any edit fails to match, the file is left unchanged. Provide either the single form or the `edits` array, not both.
## Artifact Tools
Artifact tools let an agent save substantial deliverables for the user to view in the session UI without granting broad filesystem write access.
### Configuration
```yaml theme={"system"}
tools:
artifacts: true
```
Optional custom project-relative directory:
```yaml theme={"system"}
tools:
artifacts:
dir: .agentuse/artifacts
```
When enabled, the agent receives:
| Tool | Description |
| - | - |
| `artifact_save` | Save a report, plan, spec, HTML page, chart, or other deliverable under the artifact directory and link it to the current run |
| `artifact_list` | List saved artifacts from the manifest, filterable by current session or group |
`artifact_save` writes under `.agentuse/artifacts/` by default, records metadata in a manifest, and returns a viewable session URL when a session is active. Markdown artifacts can include `title` and `tags`, which are merged into frontmatter. To read an artifact's content later, use `filesystem_read` on the returned path.
## Metrics Tool
The metrics tool lets an agent record business-metric facts (counts and amounts) about work it just completed, e.g. "chased 4 invoices totaling \$11,200". Records land in the reserved shared `metrics` store and roll up on the serve Home page and over the JSON API, so the numbers a dashboard shows are deterministic tool writes, never model-computed sums.
### Configuration
```yaml theme={"system"}
tools:
metrics: true
```
When enabled, the agent receives:
| Tool | Description |
| - | - |
| `record_metric` | Record a metric fact `{ metric, value?, unit?, count?, note? }` into the shared `metrics` store |
### Fields
| Field | Type | Description |
| - | - | - |
| `metric` | `string` | Stable snake\_case name in verb\_object form (e.g. `invoices_chased`). The grouping key: keep it identical across runs |
| `value` | `number` | Numeric magnitude, e.g. total amount in whole currency units |
| `unit` | `string` | Unit of `value` (e.g. `usd`, `minutes`). A metric name should always use the same unit |
| `count` | `number` | Number of items handled |
| `note` | `string` | Short human context shown alongside the number |
At least one of `value` or `count` is required.
### Idempotency
Records are upserted keyed on `(sessionId, metric)`: a retried or resumed run overwrites its own earlier record instead of double-counting, and recording the same metric twice in one run is last-write-wins. This is what makes the numbers trustworthy enough to display. Runs without a session id (rare) cannot be deduplicated and always create a new record.
The runtime stamps `sessionId` and the agent id onto every record; the model cannot spoof provenance. Each record is a regular store item (`type: "metric"`, tagged with the metric name) in `.agentuse/store/metrics/`, browsable at `/stores/metrics` and readable programmatically via `GET /api/stores/metrics`. In mock mode the write is not skipped, it is isolated: the `metrics` store is re-rooted along with every other store under `.agentuse/store-mock/`, so a test run's records are inspectable there and never enter the real `metrics` store the dashboards read. See [the store guide's note on mock runs](/guides/store#what-is-the-store).
## Bash Tool
Controls which shell commands can be executed and in which directories.
### Configuration
```yaml theme={"system"}
tools:
bash:
commands:
- "git *"
- "npm *"
- "pnpm *"
gated:
- "npm publish *"
allowedPaths:
- /tmp
- ~/workspace
timeout: 2m
```
### Fields
| Field | Type | Default | Description |
| - | - | - | - |
| `commands` | `string[]` | `[]` | Auto-run allowlist of command patterns (supports `*` wildcard). May be omitted when every allowed command comes from `gated` or trusted skills |
| `gated` | `string[]` | `[]` | Command patterns that run only after human approval, enforced by a per-action lease. Also runnable (the effective allowlist is `commands` plus `gated`); a match in both is gated. Declaring `gated` implies the approval gate. See [Gated commands](/guides/approval-gates#gated-commands-mechanical-enforcement). |
| `allowedPaths` | `string[]` | `[]` | Additional directories beyond project root |
| `timeout` | `string` | `"2m"` | Command timeout as a duration string (`"30s"`, `"2m"`, `"500ms"`). Bare numbers are **rejected** with a corrective error: this field was historically milliseconds while every other timeout field is seconds, so a bare number is ambiguous by construction |
When no config timeout is set, the model may pass a per-call `timeout`: a duration string, or a bare number meaning milliseconds (kept for model familiarity). A bare per-call number under 1000 is rejected with a corrective error (it is always a seconds-vs-milliseconds mixup; a real sub-second timeout must be written as `"500ms"`).
### Command Patterns
Both `commands` and `gated` support `${root}`, `${agentDir}`, and `${tmpDir}`.
These resolve from the runtime path context before matching, including approval
enforcement and gated mocks. For example, `python3 ${agentDir}/check.py *`
matches the resolved script path. This does not expand shell input or environment
variables. `${agentDir}` requires an agent loaded from a file. Replacement paths
containing whitespace or shell/wildcard metacharacters fail configuration rather
than changing pattern meaning; use a project-relative command for those paths.
Commands use simple wildcard matching:
| Pattern | Matches |
| - | - |
| `git *` | Any git command (git status, git commit, etc.) |
| `npm install` | Only `npm install` (exact match) |
| `*` | Any command (use with caution) |
### allowedPaths Behavior
The `allowedPaths` field uses **containment** - a path grants access to all files and subdirectories within it:
```yaml theme={"system"}
bash:
allowedPaths:
- /tmp # Allows /tmp, /tmp/foo, /tmp/foo/bar, etc.
- ~/workspace # Allows all of ~/workspace/**
```
Project root is always accessible for bash commands. Use `allowedPaths` for directories outside the project.
### Examples
```yaml theme={"system"}
# Development setup with common tools
bash:
commands:
- "git *"
- "npm *"
- "pnpm *"
- "bun *"
- "tsc *"
- "eslint *"
# CI/CD with restricted access
bash:
commands:
- "npm test"
- "npm run build"
timeout: 5m
# Multi-project setup
bash:
commands:
- "git *"
- "make *"
allowedPaths:
- ~/projects/shared-lib
- /opt/tools
```
### Output Limits
The Bash tool retains at most **4MB** (`AGENTUSE_BASH_CAPTURE_BYTES`) as canonical output for reusable results. When command output exceeds that cap, AgentUse keeps a **head + tail** slice (40% head / 60% tail by default), saves the complete stream as a session artifact, and marks the result as truncated. A truncated capture never receives a reusable `resultId` because that ID must always represent complete data.
Independently, any direct JSON or text result over **10KB** (`AGENTUSE_TOOL_INLINE_RESULT_BYTES`) becomes a reusable result handle before it reaches the model. This smaller limit prevents a large result from being re-sent on every subsequent model step.
Queries through the `results` tool can return up to **20KB** (`AGENTUSE_RESULT_QUERY_BYTES`) inline. They never create recursive result handles.
Bash stream fields use the same bounded captures as `output`. Check
`metadata.truncated` before parsing them. Keeping `output` for compatibility
means the serialized result also contains a combined copy of the streams, so it
can reach the inline-result limit sooner. Stored results preserve the separate
fields: use a query such as `.stdout | fromjson | .items` to inspect JSON stdout
without including stderr diagnostics.
Provider-native and binary results with native model-output conversion are excluded from this inline-result limit.
Because every tool result is re-sent to the model on each subsequent step, a single large output inflates input-token usage for the rest of the run. Prefer commands that emit only what you need, for example `git diff --stat` instead of a full `git diff` over high-churn files. See [Tool Output environment variables](/reference/environment-variables#tool-output) to tune the caps.
## Sandbox Tool
When a `sandbox` is configured in the agent frontmatter, the `sandbox__exec` tool is injected for running commands inside the Docker container. File I/O is handled by the filesystem tool, no separate sandbox file tools are needed.
The sandbox tool is only available when `sandbox` is configured. See the [Sandbox guide](/guides/sandbox) for setup instructions.
### `sandbox__exec`
Execute a shell command inside the Docker container.
| Parameter | Type | Default | Description |
| - | - | - | - |
| `command` | `string` | Required | Shell command to execute |
| `cwd` | `string` | Project root | Working directory inside the container |
Returns `stdout`, `stderr`, and `exitCode`.
### Mount Mode
Each filesystem path is mounted at its **real host path** with per-path mode derived from permissions:
* **Read-only**, No `write` or `edit` permissions for that path
* **Read-write**, `write` or `edit` permissions granted for that path
Paths inside the container mirror the host (no `/workspace/` alias). Changes made by the filesystem tool on the host are visible inside the container via the bind mount.
## Run Outcome Tool
The `report_outcome` tool is always available, no configuration needed. Every agent ends its run by calling it once with one of three statuses.
### `report_outcome`
| Parameter | Type | Default | Description |
| - | - | - | - |
| `status` | `"complete" \| "idle" \| "incomplete"` | Required | How the run ended, judged against the requested objective |
| `headline` | `string` | Required | One line. Complete: what the run achieved. Idle: what it checked and why nothing was due. Incomplete: the blocker and what a human must fix |
| `details` | `string` | Optional | Markdown body, only when the headline cannot carry the substance |
| `artifacts` | `string[]` | Required | Paths or URLs of substantive deliverables produced or changed in this run. Excludes routine bookkeeping and pre-existing outputs. `[]` for idle runs |
| `rejectionOnly` | `boolean` | Optional | Incomplete only. `true` when a human rejection is the sole blocker |
| `blocker` | `{ kind, subject }` | Required when `incomplete` | Why the run stopped. `kind` is one of `missing_tool`, `missing_package`, `bad_input`, `no_access`, `service_down`, `waiting_on_human`, `rejected_by_human`, `other`. `subject` is the one stuck thing as a short exact name (`birdc`, `boto3`, `quora.com`), not a sentence |
What each status does:
* **`complete`**: the objective was achieved. The call is the run's answer and ends the run. The session is `completed`.
* **`idle`**: a successful check found no action due: nothing eligible, no alert condition met, or the intended work was already handled before this run. Routine logs, checkpoints, watermarks, audit notes, and monitoring-state updates do not turn an idle check into delivered work; exclude them from `artifacts`, which must be `[]`. A requested report, analysis, or other substantive deliverable actually produced by this run is `complete`, even when it recommends no action. An idle run ends successfully and its durable session status remains `completed`; the run JSON carries `result.idle: true`, and the sessions list exposes an Idle badge and filter separately from Done. A stretch of idle runs can help reveal changes in an agent's supply of eligible work.
* **`incomplete`**: a required outcome was not delivered because something failed, including due work the agent found but could not move. The run keeps going only for bookkeeping. When it ends, the session is persisted as `error` with code `INCOMPLETE`. The blocker kind is stored in `error.cause`, with `error.subject` and `error.causeSource` (`runtime`, `approval`, `agent`, or `inferred`) saying how it was established:
* A failed tool call about the same thing (`command not found`, `No module named`, `Cannot find module`) overrides the agent's chosen kind
* A sub-agent's proven blocker passes to its parent
* `waiting_on_human` and `rejected_by_human` show as `incomplete` in the session list, exit 0, and settle the Slack run card as "run incomplete" without a failure push
* Any other blocker, or none, stays an `error`: the `failure` event fires and the exit code is 1
* `agentuse sessions show` displays the headline under the error section
The runtime system prompt already teaches every agent these statuses and tells it to choose `incomplete` when unsure between idle and incomplete. Agent files should not restate this mechanic; only add domain judgment about what counts as blocked, done, or genuinely empty for that agent.
Sessions recorded before `report_outcome` used two tools, `report_complete` and `report_incomplete`. They still display and reconcile the same way, and a session suspended before the change resumes with those tools. An old `report_complete` never reads as idle, since it cannot say whether the run did anything.
## Security Considerations
### Filesystem Tool
* **Sensitive files blocked**: `.env`, `.env.local`, etc. are blocked by default
* **Symlink resolution**: Symlinks are resolved to prevent escape attacks
* **Path traversal prevention**: `../` sequences are normalized and validated
### Bash Tool
* **Command allowlist**: Only explicitly allowed commands can run
* **Directory restrictions**: Commands can only access project root and `allowedPaths`
* **Environment sanitization**: Dangerous environment variables are cleared
* **Timeout enforcement**: Commands are killed after timeout
Be careful with broad command patterns like `*` or `bash *`. Prefer explicit command allowlists.
# Chart Blocks
Source: https://docs.agentuse.io/reference/chart-blocks
Emit inline charts from agent responses with agentuse:chart fenced blocks
Agents can embed small charts directly in their responses by writing a fenced
code block tagged `agentuse:chart`. The serve web UI renders the block as an
inline SVG chart in the session log; every other surface (CLI, plain text,
push) sees the raw JSON block, so sessions stay portable and greppable.
The block carries **data, not presentation**. Layout, colors, and theming are
owned by the renderer, so old sessions keep improving as the renderer does.
## Format
````markdown theme={"system"}
```agentuse:chart
{
"type": "bar",
"title": "New subscribers by day",
"categories": ["Jul 7", "Jul 8", "Jul 9", "Jul 10", "Jul 11"],
"series": [
{ "name": "Trials", "values": [12, 18, 9, 22, 17] },
{ "name": "Paid", "values": [3, 5, 2, 7, 6] }
]
}
```
````
## Fields
| Field | Type | Required | Notes |
| - | - | - | - |
| `type` | `"bar"` \| `"line"` | yes | Grouped bars, or one line per series |
| `title` | string | no | Names the chart; shown as the figure caption. Always set it, without one the legend is the only label |
| `categories` | string\[] | yes | Ordinal x-axis values, max 60 |
| `series` | `{ name, values }[]` | yes | 1 to 6 series; each `values` array must match `categories` in length; numbers only. `data` is accepted as an alias for `values`, but emit `values` |
| `yLabel` | string | no | Y-axis label shown beside the title |
| `unit` | string | no | e.g. `"%"`, `"ms"`; shown in the caption, tooltips, and the data table |
## Constraints and fallback
* Max 6 series and 60 categories; labels are capped at 120 characters. More
series than that should be folded into an "Other" series by the agent.
* Values must be finite JSON numbers. Negative values are supported (bars
extend below the zero line).
* Unknown fields are ignored. Anything that fails validation, including
malformed JSON, renders as a plain code block instead of a chart: the
content is never lost, it just isn't drawn.
* Pick `bar` for magnitude comparisons and funnels, `line` for
change-over-time. One chart, one y-scale: for two measures of different
scale, emit two chart blocks.
## Rendering guarantees
* Chart colors follow the app theme (light and dark) from a fixed,
colorblind-validated palette. Series are colored by position, so keep the
most important series first.
* Every chart includes hover tooltips per mark, a legend when there are two
or more series, and a collapsible **Data** table for accessibility and
copy-paste.
# CLI Commands
Source: https://docs.agentuse.io/reference/cli-commands
Complete reference for all AgentUse CLI commands
## agentuse run
Execute an agent file.
### Syntax
```bash theme={"system"}
agentuse run [prompt...] [options]
```
### Arguments
Path to agent file (.agentuse or .md extension) or HTTPS URL
Optional additional prompt to append to the agent's instructions
### Options
```bash theme={"system"}
-q, --quiet Suppress info messages (only show warnings/errors)
-d, --debug Enable verbose debug logging
--no-code-mode Disable the default code_exec tool for controlled comparison and debugging
--no-tty Disable TUI output (plain logs for piping/automation)
-v, --verbose Show detailed execution information
--timeout Maximum execution time in seconds (default: 300)
-C, --directory Run as if agentuse was started in instead of the current directory
--env-file Path to custom .env file
-m, --model Override the model specified in the agent file
--mock Mock all tool outputs with the LLM instead of executing them (no real side effects). Requires --mock-model.
--mock-model Model that generates mock tool outputs (required with --mock; pick a cheap, reachable model)
--mock-approval [d] Resolve the await_human gate deterministically instead of suspending: approve (default), reject, or comment:
```
The `--quiet` and `--debug` options cannot be used together.
You can also set `NO_TTY=true` to force plain logging without spinners.
### Directory and Path Resolution
#### Directory Override (-C, --directory)
The `-C` or `--directory` option is the starting directory for the command:
```bash theme={"system"}
# Without -C: runs from current directory
agentuse run agent.agentuse
# With -C: starts from the specified directory
agentuse run agent.agentuse -C /path/to/project-or-subdir
```
#### Project Root Detection
AgentUse searches from the current directory upward for `.agentuse/`, `.git/`, or `package.json`. If none are found, the starting directory is the project root.
The project root is used for:
* Loading `.env` files
* Finding plugins in `.agentuse/plugins/`
* Owning shared stores in `.agentuse/store/`
* Grouping session state
For `agentuse serve`, `-C` also defines the served scope: only `.agentuse` files under that directory are exposed, while state still belongs to the detected project root.
This is useful for:
* Running agents from different projects
* CI/CD environments with complex directory structures
* Testing with different configurations
#### Path Resolution Rules
Subagent paths and MCP server commands are resolved relative to the **agent file's directory**.
See [Agent Syntax - Subagents](/reference/agent-syntax#subagents) for complete path resolution examples.
### Model Override
The `--model` option allows you to override the model specified in an agent file at runtime. This is useful for:
* **Testing**: Compare agent behavior across different models
* **Cost Optimization**: Use cheaper models for development/testing
* **Environment-Specific Models**: Different models for dev/staging/production
* **Quick Experiments**: Try new models without editing files
#### Format
```
provider:model[:env]
```
Where:
* `provider`: A built-in provider (`anthropic`, `openai`, `openrouter`, `opencode-go`, `bedrock`) or a custom provider name
* `model`: The specific model name (e.g., `claude-sonnet-4-6`, `gpt-5.5`, `glm-5-flash:q4_K_M`), or a [version alias](/reference/models#version-aliases) such as `claude-sonnet`
* `env`: Optional environment suffix for API keys (e.g., `dev`, `prod`, or full env var name), built-in providers only
A configured `@name` alias also works: `--model @fast`.
#### Examples
```bash theme={"system"}
# Override with OpenAI GPT-5
agentuse run agent.agentuse --model openai:gpt-5.6
agentuse run agent.agentuse --model opencode-go:kimi-k2.7-code
# Use Anthropic Claude Haiku for quick testing
agentuse run agent.agentuse -m anthropic:claude-haiku-4-5
# Track the newest model in a line, or use a configured alias
agentuse run agent.agentuse -m anthropic:claude-sonnet
agentuse run agent.agentuse -m @fast
# Use different API key via environment suffix
agentuse run agent.agentuse --model openai:gpt-5.6:dev
agentuse run agent.agentuse --model opencode-go:kimi-k2.7-code:dev
# This will use OPENAI_API_KEY_DEV instead of OPENAI_API_KEY
# Use specific environment variable
agentuse run agent.agentuse --model anthropic:claude-sonnet-5:ANTHROPIC_API_KEY_PERSONAL
```
When overriding models, provider-specific options (like OpenAI's `reasoningEffort`)
will be ignored if you switch to a different provider.
An explicit model override propagates to every nested sub-agent. Without
`--model`, each agent uses the model declared in its own file; a parent's
configured model is not inherited. Alias fallback candidates and cooldowns
propagate as one resolved policy and remain stable across session resume.
## agentuse test
Choose what you want to check:
| Command | Description |
| - | - |
| `agentuse test workflow [prompt...]` | Check the agent's steps and approval branches using simulated tool responses. |
| `agentuse test result --session ` | Generate from a past job's evidence and compare the new result with the original. |
### Workflow options
```text theme={"system"}
--scope all|gated Default: all. Gated simulates only gated bash; other tools run live.
--approval approve (default), reject, or comment:
--mock-model Model fabricating responses; or set AGENTUSE_MOCK_MODEL
--no-code-mode Disable code_exec for comparison
```
### Result options
```text theme={"system"}
--session Required real source session; finished or awaiting approval
--selector-model Evidence selector on first use; defaults to the agent model
--judge Optional local agent defining quality criteria, run without tools
```
Result tests reuse the first validated evidence selection for the source session.
They load current instructions and explicit read-only reference files. They do
not execute workflow tools or expose the old draft to the writer or judge.
Without a judge, `generated` means comparison available, not quality passed.
With a judge, `passed` means the new result meets its criteria, not proof of
improvement. `failed`, `incomplete`, and `error` return exit code 1; `generated`
and `passed` return 0. Reports include the evidence path and reference hashes.
Both modes accept `--quiet`, `--debug`, `--no-tty`, `--compact`, `--timeout`,
`-C`, `--env-file`, `--model`, and `--json`. Put options after the mode.
```bash theme={"system"}
agentuse test workflow reply.agentuse --approval reject
agentuse test result reply.agentuse --session
agentuse test result reply.agentuse --session --judge quality.agentuse --json
```
Compatibility: `test [prompt...]` retains adaptive mocking, and
`test --replay ` retains strict recorded-call replay. Use `./workflow`
or `./result` to refer to files whose names collide with the new subcommands.
See [Testing agents](/guides/testing-agents) for evidence selection, isolation,
limitations, approval simulation, and the complete workflow.
### Full mock (`--scope all`, or `run --mock`)
Full-scope mock answers **every** tool call with an LLM-generated result instead of executing it. The agent runs for real; only tool execution is faked. The same mode is available as low-level plumbing on `run`:
```bash theme={"system"}
agentuse run agent.agentuse --mock --mock-model anthropic:claude-haiku-4-5
```
**Use the lowest-end model you can reach for `--mock-model`.** Mocking is not a reasoning task: the model only has to fabricate a plausible result for a tool given its name and arguments. Your agent's *actual* reasoning still runs on its own model, untouched. A small, fast model produces fine mock output while keeping cost and rate-limit pressure low, which matters because mock fires one LLM call for **every** tool result (and they run concurrently when the agent batches tool calls).
Good low-end picks, by provider:
| Provider | Suggested `--mock-model` |
| - | - |
| `anthropic` | `anthropic:claude-haiku-4-5` |
| `openai` | `openai:gpt-5.4-nano` |
| `openrouter` | `openrouter:deepseek/deepseek-v4-flash` |
Pick one in a provider you're authenticated for. (Model IDs drift over time; the current low-end tier is the rule, not these exact names.)
* **A mock model is required.** Mock fires an LLM call for *every* tool result, so it must run on a model you can reach. It is deliberately **not** defaulted to the agent's own model: that ran mock onto the agent's premium, rate-limited token and produced opaque `429`s. Provide it per run with `--mock-model`, or set a global default once via `AGENTUSE_MOCK_MODEL` in the shell, `~/.agentuse/.env`, or the [`env` block of `~/.agentuse/config.json`](/reference/configuration-files#global-env-defaults). The flag wins over all of them.
* **Sub-agents run for real**; their leaf tools are mocked.
* **The approval gate stays real under `run --mock`**: `await_human` still suspends so you can verify the agent pauses for approval. Pass `--mock-approval` for fully-unattended runs (`agentuse test` defaults to this): the gate resolves **deterministically** (no LLM plays the reviewer) instead of suspending.
* `--mock-approval` (or `--mock-approval approve`) auto-approves. The approval grants the [gated-command lease](/guides/approval-gates) derived from the gate's `changes[]` exactly like a real reviewer approval, so `tools.bash.gated` flows complete end-to-end. On a pick gate the recommended option is chosen (else the first), returned as `choice`.
* `--mock-approval reject` forces the reject branch: the gate seals (terminal for the run) so you can test the agent's cleanup path.
* `--mock-approval comment:` forces the revise-and-re-gate branch with `` as the reviewer comment. The comment applies to the **first** gate only; the re-gate that follows is approved, so the run exercises the revision path and still finishes. (Repeating the comment on every gate would loop an obedient agent until it gave up.)
MCP servers still connect at startup for tool discovery, but no tool executes (no mutations). Mock outputs are non-deterministic; mocked approval decisions are deterministic.
### Remote Agent Security
When running agents from remote URLs:
1. **HTTPS Only**: Only HTTPS URLs are allowed for security
2. **File Extension**: Remote agents must have `.agentuse` extension
3. **Interactive Confirmation**: AgentUse will show a security warning with options:
* `[p]review` - Fetch and display the agent content before running
* `[y]es` - Execute the agent directly
* `[N]o` - Abort execution (default)
Example security prompt:
```
⚠️ WARNING: You are about to execute an agent from:
https://example.com/agent.agentuse
Only continue if you trust the source and have audited the agent.
[p]review / [y]es / [N]o:
```
### Examples
```bash theme={"system"}
# Run agent from current directory
agentuse run hello.agentuse
# Run agent from subdirectory
cd agents/subfolder
agentuse run my-agent.agentuse # Finds .env and plugins at project root
# Change to different directory first with -C
agentuse run agent.agentuse -C /my/project # Same as: cd /my/project && agentuse run agent.agentuse
# Run agent from a different project
agentuse run newsletter/writer.agentuse -C ~/projects/content
# Use custom environment file
agentuse run agent.agentuse --env-file .env.production
# Run with additional prompt
agentuse run assistant.agentuse "Help me write an email"
# Run with multi-word prompt
agentuse run code-review.agentuse "focus on security and performance issues"
# Run remote agent (requires HTTPS and .agentuse extension)
# Shows security warning and requires confirmation
agentuse run https://example.com/agent.agentuse
# Run remote agent with additional prompt
agentuse run https://example.com/agent.agentuse "use production settings"
# Run with debug output
agentuse run agent.agentuse --debug
# Run with additional prompt and verbose output
agentuse run agent.agentuse "be thorough" --verbose
# Run with custom timeout
agentuse run agent.agentuse --timeout 600
# Run quietly (only warnings/errors)
agentuse run agent.agentuse --quiet
# Disable TUI output for piping/automation
agentuse run agent.agentuse --no-tty
# Override model at runtime
agentuse run agent.agentuse --model openai:gpt-5.4-mini
# Override model and add prompt
agentuse run agent.agentuse "be concise" --model anthropic:claude-haiku-4-5
# Use development API key with model override
agentuse run agent.agentuse -m openai:gpt-5.6:dev
# Override model for agent with sub-agents (all will use the same model)
agentuse run orchestrator.agentuse --model openai:gpt-5.4-mini
```
### Replay a recorded session
```bash theme={"system"}
agentuse test --replay [--json] [--model ]
```
Generate with current instructions and recorded tool results. Stops at the first
proposal before automated review, final output, or an unmatched call. Never
executes live tool operations or fabricates missing results. See
[Replay recorded inputs](/guides/replay) for matching and reference-file behavior.
## agentuse sessions
View and resume AgentUse sessions.
### Syntax
```bash theme={"system"}
agentuse sessions list [options]
agentuse sessions show [options]
agentuse sessions resume [options]
agentuse sessions reconcile [options]
agentuse sessions backfill-blockers [options]
agentuse sessions path [options]
```
`agentuse sessions` is a shortcut for `agentuse sessions list`.
Session data is stored globally and partitioned by project. CLI session commands default to the current project; use `--all` or `--all-search` when you are not sure which project owns a session.
### List Sessions
```bash theme={"system"}
agentuse sessions list
agentuse sessions list --all
agentuse sessions list --project ../other-project
```
List options:
```bash theme={"system"}
-s, --subagents Include subagent sessions
-n, --limit Limit number of sessions to show
-j, --json Output as JSON
--no-mock Hide mock/test runs (listed by default, marked "· mock")
--all Show sessions across all projects
--project [path] Show sessions for a project path; defaults to current project
```
### Show a Session
```bash theme={"system"}
agentuse sessions show 01K...
agentuse sessions show 01K... --all-search
agentuse sessions show 01K... --project ../other-project
```
Show options:
```bash theme={"system"}
-j, --json Output as JSON
-f, --full Show full tool input/output
--project [path] Search a project path; defaults to current project
--all-search Search all projects if not found in the selected project
```
### Resume a Session
Use `agentuse sessions resume` for local continuation. It supports suspended approval sessions and ended sessions.
For a suspended approval session:
```bash theme={"system"}
agentuse sessions resume 01K... --approve
agentuse sessions resume 01K... --approve "Looks good"
agentuse sessions resume 01K... --approve --choice candidate-2
agentuse sessions resume 01K... --reject "Not ready"
agentuse sessions resume 01K... --comment "Please revise the CTA"
agentuse sessions resume 01K... --comment "Keep intros factual, not salesy" --remember
agentuse sessions resume 01K... --comment "Please revise with citations" --remember "Always include source links before publishing."
```
The CLI uses local session access as the trust boundary, so approval resumes do not require a resume token. The decision rules are the same as on the approval page: a pick gate (one with `options`) needs `--choice ` naming the option to approve, `--choice` only goes with `--approve`, and a draft that strict automated review sent back for revision guidance can be commented on or rejected but not approved.
`--remember` saves the comment as a future instruction, and requires `--comment` (a non-empty one). Bare `--remember` reuses the comment text; passing a value (`--remember "..."`) overrides it. Passing `--remember` is itself the opt-in, so saving needs no `learning` config on the agent. The comment is still the feedback for this revision; the instruction is distilled from it, stored as `src:manual`, and injected into future runs once the agent has `learning.apply` enabled. It is also vetted against the agent's own instructions: a note that contradicts them is still saved, but quarantined with the conflict named rather than injected.
For a suspended non-approval `await_*` tool (approval gates refuse `--tool-result`; use the decision flags above):
```bash theme={"system"}
agentuse sessions resume 01K... --tool-result '{"status":"done"}'
```
For a completed or errored session, AgentUse starts a new run from the original agent file with continuation context:
```bash theme={"system"}
agentuse sessions resume 01K... --prompt "Continue from here and add tests"
```
Resume options:
```bash theme={"system"}
-C, --directory Run as if agentuse was started in
--project [path] Search a project path; defaults to current project
--all-search Search all projects if not found in the selected project
-d, --debug Enable debug logging for resume
```
### Reconcile Stuck Sessions
Settle sessions still marked `running` whose owning process is gone. This is the same owner-liveness check `agentuse serve` performs at startup, but it sweeps as far back as you ask instead of the daemon's 30-day window.
```bash theme={"system"}
agentuse sessions reconcile [options]
```
Reconcile options:
```bash theme={"system"}
--lookback How far back to scan: a day count, or "all" (default: all)
--dry-run Report what would be settled without writing
-j, --json Output as JSON
--all Reconcile across all projects
--project [path] Reconcile a project path; defaults to current project
```
A run that is still executing anywhere is never touched: a live worker, a worker released across a daemon restart, or a plain terminal `agentuse run` all keep their session as-is, because the session records its owning process and reconcile checks that the process is actually alive. A 10-minute recency window backs that up, so a session written to very recently is left alone even if it comes from a build that predates owner tracking.
Sessions suspended on a subagent that died are settled the same way, so a manager waiting on a child that will never report back stops sitting in limbo.
Why this exists: runs orphaned before serve's 30-day startup window stayed `running` forever, inflating the dashboard's needs-attention counts with work that ended long ago.
```bash theme={"system"}
# See what is stuck without changing anything
agentuse sessions reconcile --dry-run
# Settle everything in this project, however old
agentuse sessions reconcile
# Sweep the last week across every project, as JSON
agentuse sessions reconcile --all --lookback 7 --json
```
### Backfill Blockers
Give older `INCOMPLETE` runs a blocker so they group with new ones, and dismiss failures too old to act on. It only adds fields: status and messages are never rewritten.
```bash theme={"system"}
agentuse sessions backfill-blockers [options]
```
Backfill options:
```bash theme={"system"}
--days Backfill failures last touched within this many days; dismiss older ones (default: 14)
--dry-run Report what would change without writing
-j, --json Output as JSON
--all Sweep every project
--project [path] Sweep a project path; defaults to current project
```
### Show Storage Path
```bash theme={"system"}
agentuse sessions path
agentuse sessions path --project ../other-project
```
## agentuse serve
Start the AgentUse HTTP daemon to run agents via API. This enables integration with external applications, webhooks, approvals, Slack notifications, or any system that can make HTTP requests.
### Syntax
```bash theme={"system"}
agentuse serve [options]
```
### Options
```bash theme={"system"}
-p, --port Port to listen on (default: 12233)
-H, --host Host to bind to (default: 127.0.0.1)
-C, --directory Directory to serve agents from; project state is detected upward
--default Default project for POST /api/run when `project` is omitted
-d, --debug Enable debug mode
--no-code-mode Disable the default code_exec tool for every run launched by this daemon
--public-url Externally reachable base URL used in approval links (or config serve.publicUrl)
--no-auth Disable API key requirement for exposed hosts (dangerous)
--no-log-file Disable writing serve logs to a file
--open Open the Web UI in the default browser after startup
--hide-agent-source Hide raw agent source in the dashboard and /api/agents/detail
```
### Serving Multiple Projects
AgentUse runs one serve daemon at a time. Repeat `-C` on that daemon to serve multiple scopes/projects:
```bash theme={"system"}
agentuse serve -C ./projA -C ./projB
```
Project ids default to the `-C` directory basename. Duplicate ids fail startup. Each scope detects its project root independently, and each project loads its own `.env` / `.env.local` in its worker process.
Use the request `project` field to choose a project. In multi-project mode, omitting it returns `400 PROJECT_REQUIRED` unless `--default ` is set.
Starting a second daemon fails with the PID, address, projects, and log path of the daemon that is already running. This keeps approval links, Slack replies, session resumes, and API traffic routed through one owner.
### Global Config
You can put serve defaults in `~/.agentuse/config.json`. See [Configuration Files](/reference/configuration-files#global-serve-config) for the schema and CLI override behavior.
### Authentication
When binding to exposed hosts (not `127.0.0.1` or `localhost`), API key authentication is required:
```bash theme={"system"}
# Set API key for authentication
export AGENTUSE_API_KEY="your-secret-key"
# Start server on all interfaces
agentuse serve --host 0.0.0.0
```
Clients must include the key in requests:
```bash theme={"system"}
curl -X POST http://server:12233/api/run \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{"agent": "my-agent.agentuse"}'
```
Use `--no-auth` to bypass authentication (dangerous for production).
### API Endpoints
All JSON endpoints are served under the `/api/*` prefix; the un-prefixed root
paths (`/`, `/agents`, `/sessions`, `/schedules`, `/stores`, `/approvals`) serve
HTML dashboard pages. `GET /` is the dashboard home: it links to those pages and
lists the served projects with their agent and schedule counts. The per-session
page `/sessions/:id` and its action
subroutes (`/decision`, `/continue`, `/status`) carry their own capability auth
(session token / API key / local). `POST /run`, `POST /resume/:id`, and the
`POST /approvals/:id/...` action endpoints remain reachable at their original
paths for backward compatibility, and `GET /approvals/:id` redirects to
`/sessions/:id` (prefer the `/api/*` and `/sessions` paths; the legacy aliases
will be removed later).
#### GET /api
Returns version, default project, and served projects. (`GET /` serves the HTML
dashboard built from the same data.)
```json theme={"system"}
{
"version": "0.12.0",
"update": {
"currentVersion": "0.12.0",
"latestVersion": "0.18.0",
"packageManager": "npm",
"command": "npm install -g agentuse@latest"
},
"default": "projA",
"projects": [
{ "id": "projA", "path": "/abs/path/to/projA", "agentCount": 3, "scheduleCount": 1 },
{ "id": "projB", "path": "/abs/path/to/projB", "agentCount": 2, "scheduleCount": 0 }
]
}
```
`update` is present only when the cached npm registry result contains a newer
AgentUse version from npm's `latest` dist-tag. The dashboard uses it for its
dismissible update banner.
`default` is `null` in multi-project mode without `--default`; single-project mode returns the sole project id.
#### POST /api/run
Execute an agent and receive the result. (Legacy alias: `POST /run`.)
**Request Body:**
```json theme={"system"}
{
"agent": "path/to/agent.agentuse",
"project": "projA",
"prompt": "Optional additional prompt",
"model": "anthropic:claude-sonnet-5",
"timeout": 300,
"maxSteps": 100
}
```
| Field | Type | Required | Description |
| - | - | - | - |
| `agent` | string | Yes | Path to agent file (relative to that project's root) |
| `project` | string | Conditional | Required in multi-project mode unless `--default` is set |
| `prompt` | string | No | Additional prompt to append to agent instructions |
| `model` | string | No | Override the model specified in agent file |
| `timeout` | number | No | Maximum execution time in seconds (default: 300) |
| `maxSteps` | number | No | Maximum number of tool call steps |
**Response (JSON):**
```json theme={"system"}
{
"success": true,
"result": {
"text": "Agent response text",
"finishReason": "end-turn",
"duration": 1234,
"tokens": { "input": 500, "output": 200 },
"toolCalls": 3
}
}
```
**Error Response:**
```json theme={"system"}
{
"success": false,
"error": {
"code": "AGENT_NOT_FOUND",
"message": "Agent file not found: my-agent.agentuse"
}
}
```
#### GET /api/agents
Lists the agents loaded by the daemon as JSON. `path` is relative to the project
root, exactly as accepted by `POST /api/run`. Agents that fail to parse are
reported in `errors` rather than failing the request. The browsable HTML page is
at `/agents`.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/agents"
```
```json theme={"system"}
{
"success": true,
"agents": [
{
"projectId": "projA",
"path": "daily.agentuse",
"name": "Daily Digest",
"description": "Posts a daily digest",
"model": "anthropic:claude-sonnet-5",
"schedule": "0 9 * * *"
}
],
"errors": []
}
```
`description` and `schedule` are present only when the agent declares them.
#### GET /api/agents/detail
Returns the capability summary and raw `.agentuse` source for one loaded agent.
The endpoint is operator-gated like the rest of `/api/*`, and `path` must match
an agent already loaded by the project.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/agents/detail?project=projA&path=daily.agentuse" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
The browsable agent detail hub is at `/agents//`.
#### GET /api/schedules
Lists the scheduled agents currently registered with the running daemon as JSON,
sorted by next run (soonest first, disabled last). The browsable HTML page is at
`/schedules`.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/schedules"
```
```json theme={"system"}
{
"success": true,
"schedules": [
{
"id": "3252d076-d203-4921-b1c4-013d8748406b",
"projectId": "projA",
"agentPath": "daily.agentuse",
"expression": "0 9 * * *",
"human": "Daily 9am",
"timezone": "America/Vancouver",
"enabled": true,
"jitterMs": 78721,
"nextRun": "2026-06-03T16:00:00.000Z",
"lastRun": null,
"createdAt": "2026-06-02T21:00:42.371Z"
}
]
}
```
`nextRun` and `lastRun` are ISO timestamps (or `null`). `lastResult` is included
once a scheduled run has completed, and carries the run's `sessionId` so the
dashboard can deep-link to its log.
#### GET /api/sessions
Lists top-level runs as JSON, live first and then by most recent activity. Filters:
`?agent=`, `?trigger=scheduled|manual|slack|api`, and
`?window=<1h|6h|24h|7d|30d|90d|all>` (default `24h`). Time windows use the
last update, so a recently completed long-running session remains visible. The
browsable HTML page is at `/sessions`.
`?status=incomplete` matches only runs blocked on a person; incomplete runs with any other blocker are listed under `error`.
Use `?status=idle` for successful checks with no action due, or
`?status=completed` for Done runs excluding idle. Idle rows retain the durable
`status: "completed"` and carry `outcome: "idle"`; the list's `counts.idle` and
`counts.done` are separate. Older recorded idle outcomes are recovered from the
structured tool call. Runs that reported complete are not reclassified from
their output text.
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions?agent=daily&trigger=scheduled" \
-H "Authorization: Bearer $AGENTUSE_API_KEY"
```
```json theme={"system"}
{
"success": true,
"sessions": [
{
"project": "projA",
"sessionId": "01JFN8K3M2P1",
"agent": { "id": "daily", "name": "Daily Digest", "description": "Posts a daily digest" },
"status": "completed",
"trigger": "scheduled",
"createdAt": 1717430400000,
"updatedAt": 1717430412000
}
],
"window": { "value": "24h", "hours": 24, "updatedAfter": 1717344000000 },
"errors": []
}
```
`trigger` is `scheduled`, `api`, `slack`, or `manual` (CLI runs and the default).
For large histories, opt into cursor pagination with `limit` (maximum 100) and
the opaque `nextCursor` returned by the prior response:
```bash theme={"system"}
curl "http://127.0.0.1:12233/api/sessions?limit=50"
```
Supplying `limit` changes only the list length and adds `limit` and (when more
records exist) `nextCursor`; requests without it retain the complete legacy
response. Cursors are bound to the active filters and should be treated as
opaque.
#### GET /api/sessions/:id
Returns one session including its run-log entries (`logs`). API-key gated. The
human-facing view + approve page is `/sessions/:id`; see
[Approval Gates](/guides/approval-gates#experimental-session--approval-api).
| Error Code | HTTP Status | Description |
| - | - | - |
| `NOT_FOUND` | 404 | Endpoint not found (use `POST /api/run` or `GET /api`) |
| `AGENT_NOT_FOUND` | 404 | Agent file doesn't exist |
| `PROJECT_NOT_FOUND` | 404 | Unknown project id in multi-project mode |
| `PROJECT_REQUIRED` | 400 | Multi-project request without `project` or `--default` |
| `INVALID_PATH` | 400 | Agent path outside project root |
| `INVALID_REQUEST` | 400 | Invalid JSON body |
| `MISSING_FIELD` | 400 | Required field missing |
| `TIMEOUT` | 504 | Agent execution timed out |
| `EXECUTION_ERROR` | 500 | Runtime error during execution |
| `INTERNAL_ERROR` | 500 | Unexpected server error |
### Streaming Response
For real-time output, request NDJSON streaming by setting the `Accept` header:
```bash theme={"system"}
curl -N -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-H "Accept: application/x-ndjson" \
-d '{"agent": "my-agent.agentuse"}'
```
Each line is a JSON object representing an execution event:
```json theme={"system"}
{"type": "text", "text": "Analyzing..."}
{"type": "tool-call", "name": "read_file", "args": {"path": "data.txt"}}
{"type": "tool-result", "name": "read_file", "result": "..."}
{"type": "text", "text": "Complete!"}
{"type": "finish", "finishReason": "end-turn", "duration": 2345}
```
### Examples
```bash theme={"system"}
# Start server with defaults (127.0.0.1:12233)
agentuse serve
# Start on custom port
agentuse serve --port 8080
# Bind to all interfaces (for external access)
agentuse serve --host 0.0.0.0 --port 3000
# Set the public URL used in approval review links
agentuse serve --public-url https://agentuse.mycompany.com
# Provide Slack credentials for agents that enable Slack channels
SLACK_BOT_TOKEN=xoxb-... SLACK_APPROVAL_CHANNEL=C0123456789 agentuse serve
# Serve agents from a project or subdirectory
agentuse serve -C /path/to/project-or-subdir
# Host multiple projects from one process
agentuse serve -C ./projA -C ./projB
# Default POST /api/run to projA when `project` is omitted
agentuse serve -C ./projA -C ./projB --default projA
# Start with debug logging
agentuse serve --debug
```
**API Usage Examples:**
```bash theme={"system"}
# Run an agent (JSON response)
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "agents/assistant.agentuse"}'
# Run with additional prompt
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "agents/writer.agentuse", "prompt": "Write about AI"}'
# Override model
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"agent": "agents/helper.agentuse", "model": "openai:gpt-5.4-mini"}'
# Streaming response
curl -N -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-H "Accept: application/x-ndjson" \
-d '{"agent": "agents/analyzer.agentuse"}'
# Multi-project: pick which project runs the agent
curl -X POST http://127.0.0.1:12233/api/run \
-H "Content-Type: application/json" \
-d '{"project": "projA", "agent": "assistant.agentuse"}'
# Discovery: list served projects
curl http://127.0.0.1:12233/
```
### Scheduled Agents
Agents with a `schedule` config in their frontmatter are automatically executed on schedule:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
schedule: "1h"
---
```
See the complete guide for intervals and cron expressions.
The server enables CORS by default. For production, run behind a reverse proxy with authentication.
### serve ps
Show the running `agentuse serve` daemon.
```bash theme={"system"}
agentuse serve ps [--json]
```
Shows PID, port, every served project, total agent/schedule counts, and uptime.
Multi-project daemons render one project per row under the same daemon.
```
PID PORT PROJECTS AGENTS SCHEDULES UPTIME
────────────────────────────────────────────────────────────────────────────
63398 12233 projA 12 3 2h 15m
projB
projC
```
Use `--json` for scripting. Stale entries are automatically cleaned up.
While `serve ps` shows counts across daemons, use `serve agents` and `serve schedules` to inspect what a single running daemon actually loaded.
### serve agents
List the agents loaded by the running daemon (queries its live `GET /api/agents` endpoint).
```bash theme={"system"}
agentuse serve agents [pid] [--json]
```
```
AGENT NAME MODEL SCHEDULE
────────────────────────────────────────────────────────────────────
adhoc.agentuse Adhoc Helper anthropic:claude-haiku-4-5 —
daily.agentuse Daily Digest anthropic:claude-sonnet-5 0 9 * * *
```
Omit `pid` when only one daemon is running. Agents that failed to parse are listed after the table. Use `--json` for the raw payload. When the daemon requires an API key, set `AGENTUSE_API_KEY` so the command can authenticate.
### serve schedules
List the scheduled agents in the running daemon (queries its live `GET /api/schedules` endpoint), sorted by next run.
```bash theme={"system"}
agentuse serve schedules [pid] [--json]
```
```
NEXT RUN AGENT SCHEDULE LAST RUN
──────────────────────────────────────────────────
Jun 03, 09:00 daily.agentuse Daily 9am never
```
***
## agentuse schedules
Inspect and control deployment-local schedule state without changing agent
frontmatter.
```bash theme={"system"}
agentuse schedules
agentuse schedules pause
agentuse schedules resume
```
`agentuse schedules` lists declared schedules and whether each one is active or
paused. `pause` and `resume` persist the override for the current deployment and
notify a running daemon, when present. The declared cron expression or interval
stays in the agent file and remains visible in the dashboard.
***
## agentuse models
List the recommended models, the aliases they can be reached by, and your configured default.
```bash theme={"system"}
agentuse models # recommended lineup + aliases
agentuse models anthropic # one provider
agentuse models --all # every model in the registry
agentuse models --verbose # context limits, capabilities, alias per model
```
The **Version aliases** section shows what each version-less id (`anthropic:claude-sonnet`) resolves to right now. **Your aliases** and **Default model** appear when a `models` block is configured (see [Configuration Files](/reference/configuration-files#model-defaults-and-aliases)).
### models unpin
Replace pinned model versions in agent files with version aliases, so those files track the newest release and stop needing edits:
```bash theme={"system"}
agentuse models unpin --dry-run # preview, current directory
agentuse models unpin ./agents # apply to a directory
agentuse models unpin one.agentuse # apply to a single file
```
```
agents/researcher.agentuse
anthropic:claude-sonnet-5 → anthropic:claude-sonnet (currently anthropic:claude-sonnet-5)
```
### models bump
Move superseded pins forward to the current model of the same product line, for files you want to keep pinned:
```bash theme={"system"}
agentuse models bump --dry-run
agentuse models bump ./agents
```
Both commands only rewrite model references inside an agent file's YAML frontmatter. Instructions below the frontmatter are left alone, since prose may legitimately name a specific model version. Version aliases are never rewritten by `bump`: they already track the line.
***
## agentuse plugins
Install and manage trusted AgentUse packages from Git repositories.
```bash theme={"system"}
agentuse plugins install owner/repository
agentuse plugins install git:github.com/owner/repository@v1
agentuse plugins list [--json] [--all-scopes]
agentuse plugins update [name]
agentuse plugins remove
agentuse plugins uninstall # alias
```
Add `-l` to any subcommand to use project-local package settings. `install` accepts `owner/repo`, `github:owner/repo`, `git:github.com/owner/repo@ref`, HTTPS or SSH GitHub URLs, and local directory paths (linked in place rather than cloned). `update` without a name updates every plugin in the selected scope, and reports "already up to date" for a pinned source or unchanged linked package. The shorter `agentuse install|update|list|remove` commands remain as compatibility aliases.
***
## agentuse provider
Manage providers and authentication credentials. (`auth` still works as a hidden alias.)
### provider login
```bash theme={"system"}
agentuse provider login [provider] # built-ins plus installed provider plugins
agentuse provider login opencode-go
```
Amazon Bedrock authenticates via standard AWS environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, optional `AWS_SESSION_TOKEN`) or `AWS_BEARER_TOKEN_BEDROCK`. There is no `provider login bedrock` command.
### provider add
Add a custom OpenAI-compatible endpoint from the CLI (Ollama, LM Studio, vLLM,
etc.). The dashboard can additionally configure OpenAI Responses and Anthropic
Messages endpoints; see [Model Configuration](/guides/model-configuration#custom-providers).
```bash theme={"system"}
agentuse provider add ollama --url http://localhost:11434/v1
agentuse provider add lmstudio --url http://localhost:1234/v1
agentuse provider add myserver --url https://gpu.example.com/v1 --key sk-mykey
```
Then use: `agentuse run agent.agentuse -m ollama:glm-5-flash:q4_K_M`
The command prints `URL`, `API`, `Key`, and `Models` lines. Each URL and key is labelled `stored` or `from _BASE_URL` / `from _API_KEY` when an environment variable overrides it.
Colons in model names are supported, `ollama:qwen3.5:0.8b` parses as provider `ollama`, model `qwen3.5:0.8b`.
### provider remove / logout
```bash theme={"system"}
agentuse provider remove ollama # remove custom provider
agentuse provider logout openai # remove built-in credentials
```
### provider list
```bash theme={"system"}
agentuse provider list
agentuse provider list --json # machine-readable status; never includes secrets
```
## agentuse mcp
Manage logins for the HTTP MCP servers an agent uses. See [OAuth MCP Servers](/reference/agent-syntax#oauth-mcp-servers) for the agent-file side.
```bash theme={"system"}
agentuse mcp login # Log in; every agent using the same server URL shares it
agentuse mcp login --no-browser # Print the login URL instead of opening a browser
agentuse mcp status # Show how each of the agent's MCP servers signs in
agentuse mcp logout # Forget the saved login
```
`` is the agent file and `` is the server's name under `mcpServers`.
***
## agentuse skills
List and retrieve AgentUse builtin skills that ship with the installed CLI version. Use the `installed` subcommand to inspect project and user-installed skills.
### Syntax
```bash theme={"system"}
agentuse skills [subcommand] [options]
```
### Subcommands
```bash theme={"system"}
agentuse skills # List AgentUse builtin skills
agentuse skills list # Explicit builtin list command
agentuse skills get # Output builtin skill content
agentuse skills get --full
agentuse skills get --all # Output every builtin skill
agentuse skills path [name] # Print builtin skill paths
agentuse skills installed # List installed/discovered skills
agentuse skills installed get
agentuse skills installed path [name]
```
### Options
```bash theme={"system"}
-v, --verbose Show skill file paths and tool requirements when listing
-j, --json Output machine-readable JSON
--full Include supporting files when using get
--all Output every skill for the selected source when using get
```
### Builtin Skills
Builtin skills are stored in the AgentUse package `skill-data/` directory and match the installed CLI version. This mirrors the `agent-browser skills` model: agents can fetch current official instructions without reading a user's entire local skill library.
| Skill | Covers |
| - | - |
| `core` | The entry point: what AgentUse is, and which of the three below to fetch next |
| `runner` | Running agents, listing them, sessions, `serve`, schedules |
| `creator` | Authoring, improving, and reviewing `.agentuse` files |
| `tester` | Validating agents without real side effects: choosing a mock model and scope, exercising approval gates unattended, the edit-run-inspect loop, and the fidelity caveats of mock output |
### AI Coding Assistants
Install the assistant-facing AgentUse skill stub:
```bash theme={"system"}
npx skills add agentuse/agentuse
```
For local development, install from this checkout:
```bash theme={"system"}
npx skills add .
```
This installs the thin `agentuse` skill from `skills/agentuse/SKILL.md`. The stub points assistants at `agentuse skills get core`, so the real workflow guidance stays version-aligned with the installed AgentUse CLI.
### Installed Skill Locations
Installed skills are discovered from these directories (in priority order):
1. `.agentuse/skills/` - Project-specific skills
2. `$AGENTUSE_CONFIG_DIR/skills/` - User-global skills (defaults to `~/.agentuse/skills/`)
3. `.claude/skills/` - Claude ecosystem compatibility
4. `~/.claude/skills/` - Claude ecosystem compatibility
5. `~/.agents/skills/` - Shared agent skills compatibility
Symlinked skill directories and `SKILL.md` files are supported. AgentUse skips
dangling links, resolves directory real paths, and avoids circular traversal.
### Examples
```bash theme={"system"}
# List AgentUse builtin skills
agentuse skills
agentuse skills list
# Show verbose output with file paths and tool requirements
agentuse skills -v
agentuse skills --verbose
# Return machine-readable metadata
agentuse skills --json
agentuse skills list --json
# Print builtin skill content for an agent or script
agentuse skills get core
agentuse skills get runner
agentuse skills get creator
agentuse skills get tester
agentuse skills get core --full
agentuse skills get --all --json
# Print builtin paths
agentuse skills path
agentuse skills path core
# Inspect project and user-installed skills
agentuse skills installed
agentuse skills installed list --json
agentuse skills installed get code-review
agentuse skills installed get code-review --full
agentuse skills installed path code-review
```
### Output Example
```
Found 3 builtin skill(s):
agentuse builtins
core
Core AgentUse usage guide...
creator
Create, improve, and review AgentUse agent files...
runner
Run and manage AgentUse agents from the CLI...
```
Installed skills:
```
Found 2 installed skill(s):
.agentuse/skills
code-review
Review code for quality, security, and maintainability...
```
With verbose mode (`-v`):
```
Found 2 installed skill(s):
.agentuse/skills
code-review
Review code for quality, security, and maintainability...
/path/to/project/.agentuse/skills/code-review/SKILL.md
tools: Read, Bash(git:*)
```
For detailed information on creating and using skills, see the [Skills Guide](/guides/skills).
***
## agentuse doctor
Diagnose an agent's skill capability configuration. Static mode inspects the agent file; `--last-run` inspects the most recent recorded session.
### Syntax
```bash theme={"system"}
agentuse doctor [--last-run]
```
### What It Checks
Static mode:
* Recurring prompt cost per model request: the agent body, the full text of each preloaded skill, and the visible skill catalog, with a total.
* Explicit skills that don't exist on disk.
* Explicit skills with no `allow` grants.
* Commands mentioned in skill docs vs. what the agent has granted (advisory; not a permission manifest).
* Learnings: how many of the stored ones are actually applied per run, and how many are over `learning.max` and so never reach the model, with `agentuse learnings tidy ` as the fix. It also reports how many are **stale** (the agent instructions changed since they were vetted, so they are held out of injection until the next capture or tidy re-vets them), a `by channel:` breakdown of what captured them (`corrections`, `tool-errors`, `custom`, `agent`, or `legacy` for entries predating channels), and every **quarantined** entry with the reason it failed the vet. It prints the resolved `learnings file:` path, echoes any one-time notice about a legacy `learning:` form, and warns when learnings are still sitting beside the agent file at the pre-0.17.0 location where nothing reads them.
`--last-run` mode:
* Finds the latest non-subagent session for this agent.
* Reports blocked bash commands from runtime and prints a suggested `tools.bash.commands` snippet.
### Examples
```bash theme={"system"}
# Static inspection
agentuse doctor agents/research.agentuse
# Diagnose actual blocked commands from the last run
agentuse doctor agents/research.agentuse --last-run
```
### Prompt Size Warnings
Two costs recur on **every** model request, so doctor flags them:
| What | Warns above | Warns harder above |
| - | - | - |
| Preloaded skills (the full text of everything in `skills:`) | \~2,000 tokens | \~4,000 tokens |
| Visible skill catalog (a name and description per discoverable skill) | \~1,500 tokens | \~3,000 tokens |
The fix for either is the same shape: preload only what every run needs, and close discovery with `skills.auto: false` plus a shorter explicit list. Open discovery is the expensive default at scale, a machine with 100 skills installed pays roughly 11k tokens per request for the catalog alone.
Use `--last-run` after an agent fails or behaves unexpectedly. It uses real tool errors and is more accurate than static skill-doc extraction.
***
## agentuse learnings
Inspect and tidy an agent's stored learnings. Only the top few apply per run (15 by default, `learning.max`); anything past that is stored but never reaches the model, and so are entries that are quarantined (failed the vet) or stale (the agent instructions changed since they were vetted). See the [Learning guide](/guides/learning).
### Syntax
```bash theme={"system"}
agentuse learnings [--json] [--path] [--edit]
agentuse learnings tidy [--dry-run] [--model ]
agentuse learnings undo
agentuse learnings migrate [|--all] [--dry-run] [--keep-source|--delete-source]
```
### Subcommands
| Command | Description |
| - | - |
| *(none)* | List every learning by status: applied, never reaches the agent, stale (instructions changed, awaiting re-vet), quarantined (failed the vet, with the reason), in the agent file, retired. |
| `tidy` | Re-vet every learning the agent instructions have moved out from under, merge near-duplicates, sharpen learnings you have repeated, retire what is superseded, and make proven learnings permanent in the agent file. Applies immediately, then shows both diffs. Keeps making passes until another one would not help, up to five, and writes both files once at the end, so one run is one undo. Says what it is doing as it goes: a long list takes a few minutes. If it ends still over the cap, it accounts for every learning it left in force. |
| `undo` | Restore the learnings file **and** the agent file to their state before the last tidy-up, including anything that pass quarantined. |
| `migrate` | Move learnings written before v0.17.0 from beside the agent file into the AgentUse state directory. Copies first, then asks once before deleting the originals; refuses a destination that already holds learnings rather than merging; also lists any `*.learnings.md` with no matching agent file as orphaned. |
### Options
| Option | Description |
| - | - |
| `-j, --json` | Machine-readable listing. Top level: `file` (the resolved learnings path), `cap`, and `active` / `injected` / `dormant` / `stale` / `quarantined` counts. Each entry in `learnings` carries its full record, including `channel`, `injectedCount`, `approvedRuns`, `instructionsHash`, and `quarantineReason`, plus a resolved `state` and computed `injected` and `stale` flags. |
| `--path` | Print the path of the learnings file and exit. |
| `--edit` | Open the learnings file in `$EDITOR` (or `$VISUAL`), creating its directory if needed. |
| `--dry-run` | (`tidy`) Show the plan and both diffs without writing anything. (`migrate`) Report what would move, including refusals, without writing anything. |
| `--model ` | (`tidy`) Plan with this model instead of the agent's own. |
| `--all` | (`migrate`) Every agent file in the project, not one named agent. |
| `--keep-source` | (`migrate`) Keep the old files without asking. |
| `--delete-source` | (`migrate`) Delete the old files without asking. Required to delete anything when stdin is not a terminal, a non-interactive run never deletes on its own. |
### Examples
```bash theme={"system"}
# What is actually reaching this agent?
agentuse learnings agents/blog-writer.agentuse
# Where does this agent's learnings file live?
agentuse learnings agents/blog-writer.agentuse --path
# See what a tidy-up would do, then do it
agentuse learnings tidy agents/blog-writer.agentuse --dry-run
agentuse learnings tidy agents/blog-writer.agentuse
# Changed your mind
agentuse learnings undo agents/blog-writer.agentuse
# Upgrading from before v0.17.0
agentuse learnings migrate --all --dry-run
agentuse learnings migrate --all
git commit -am "chore: move learnings to the agentuse state dir"
```
A tidy-up writes proven learnings into a marked block in your `.agentuse` file. Only the bytes inside the markers change, frontmatter, comments and formatting are left exactly as they were, and `undo` restores both files byte for byte.
Learnings no longer live beside your agent file. As of v0.17.0 they live under the AgentUse state directory, and the old location is never read. Run `agentuse learnings migrate --all` once per repo to copy them across; it will ask before removing the originals. `migrate` exits non-zero if it refused any file.
***
## agentuse agents
Discover and list all agent files in the current project.
### Syntax
```bash theme={"system"}
agentuse agents [options]
```
### Options
```bash theme={"system"}
-v, --verbose Show agent file paths
```
### Examples
```bash theme={"system"}
# List all agents in the project
agentuse agents
# Show verbose output with file paths
agentuse agents -v
```
### Output Example
```
Found 3 agent(s):
agents/
assistant
General-purpose AI assistant
code-reviewer
Reviews code for quality and security
researcher
Researches topics and summarizes findings
```
***
## agentuse add
Add skills and agents from GitHub repos or local paths.
### Syntax
```bash theme={"system"}
agentuse add [options]
```
### Arguments
Source to add. Supports:
* GitHub shorthand: `user/repo` or `user/repo#branch`
* Git URL: `https://github.com/user/repo.git`
* Local path: `./path/to/repo`
* Direct skill: `./path/to/skill` (directory containing SKILL.md)
### Options
```bash theme={"system"}
--force Overwrite existing skills/agents without prompting
--all Install all skills and agents without prompting
--list List available skills and agents without installing
-s, --skill Install specific skill(s) by name (repeatable)
-a, --agent Install specific agent(s) by path (repeatable)
```
`--skill` and `--agent` install exactly the named items: `--skill` alone installs no agents, and `--agent` alone installs no skills. Combine them to install both.
### What Gets Added
| Source Pattern | Destination |
| - | - |
| `**/SKILL.md` (parent dir) | `.agentuse/skills/{skill-name}/` |
| `SKILL.md` at the source root | `.agentuse/skills/{repo-or-directory-name}/` |
| `**/*.agentuse` | Same relative path in project |
### Examples
```bash theme={"system"}
# Add from GitHub (interactive selection)
agentuse add vercel-labs/agent-skills
agentuse add vercel-labs/agent-skills#v1.0.0
# List available skills/agents without installing
agentuse add vercel-labs/agent-skills --list
# Install specific skills
agentuse add vercel-labs/agent-skills --skill react-best-practices
agentuse add vercel-labs/agent-skills -s skill-a -s skill-b
# Install specific agents
agentuse add user/repo --agent deploy.agentuse
# Install all without prompting
agentuse add user/repo --all
# Overwrite existing without prompting
agentuse add user/repo --force
# Add from local path
agentuse add ./my-skills-repo
agentuse add ./path/to/single-skill
```
### Conflict Handling
When a skill or agent already exists, you'll be prompted:
```
Skill "my-skill" already exists.
[s] Skip [o] Overwrite [a] Skip all [O] Overwrite all
```
***
## agentuse setup
First-run setup. Run it without flags in a terminal to choose how to continue:
* **Mac app** (Apple silicon only): opens `https://agentuse.io/download/mac`. The app includes its own runtime.
* **Browser**: starts `agentuse serve` and opens the guided setup in the Web UI.
* **Terminal**: creates your first project and prints the next steps.
```bash theme={"system"}
agentuse setup
agentuse setup --terminal --name my-agents --yes
```
Options:
```bash theme={"system"}
--web Continue setup in the Web UI
--terminal Continue setup in the terminal
--name Managed project name (terminal)
-y, --yes Accept the default project name without prompting
-p, --port Web setup server port (default: 12233)
-H, --host Web setup server host (default: 127.0.0.1)
--no-auth Disable server API key requirement (dangerous on publicly reachable hosts)
```
`--name` and `--yes` imply `--terminal`; `--web` cannot be combined with them. Without a terminal, pass `--web` or `--terminal`.
## agentuse help
Show help information.
### Syntax
```bash theme={"system"}
agentuse --help
agentuse -h
# Command-specific help
agentuse run --help
agentuse auth --help
```
### Examples
```bash theme={"system"}
# General help
agentuse --help
# Command-specific help
agentuse run --help
agentuse auth --help
# Show help when no arguments provided
agentuse
```
The `agentuse config` command is not yet implemented.
Configuration is currently managed through environment variables only.
## Global Options
```bash theme={"system"}
--version Show version number
--help, -h Show help for command
```
## Environment Variables
Control AgentUse behavior with environment variables. See [Environment Variables Reference](/reference/environment-variables) for complete documentation.
## Exit Codes
AgentUse uses standard exit codes:
| Code | Meaning |
| - | - |
| 0 | Success |
| 1 | General error, including an `incomplete` run (exit 0 only when the blocker is a person: `waiting_on_human` or `rejected_by_human`) |
| 2 | Authentication error |
| 3 | File not found |
| 4 | Model error |
| 5 | Tool error |
| 6 | MCP error |
| 7 | Network error |
| 130 | User interrupted (Ctrl+C) |
## Available Commands
AgentUse currently supports these commands:
```bash theme={"system"}
agentuse run [prompt...] # Run an agent with optional prompt
agentuse test workflow # Check steps with simulated tool responses
agentuse test result --session # Compare results using a past job’s evidence
agentuse serve [options] # Start the HTTP daemon to run agents via API
agentuse serve ps [--json] # Show the running serve daemon
agentuse serve schedules [pid] [--json] # List schedules the running daemon is tracking
agentuse serve agents [pid] [--json] # List agents the running daemon has loaded
agentuse sessions [list|show|resume|path] # View and resume sessions
agentuse sessions reconcile [--all] # Settle runs stuck at "running"
agentuse sessions backfill-blockers # Add blockers to older incomplete runs
agentuse setup [--web|--terminal] # First-run setup in the Mac app, browser, or terminal
agentuse provider login [provider] # Authenticate with a provider
agentuse provider add --url # Add custom provider (Ollama, LM Studio, etc.)
agentuse provider logout [provider] # Remove stored credentials
agentuse provider remove # Remove a custom provider
agentuse provider list # Show all providers and credentials
agentuse provider help # Show detailed auth help
agentuse mcp login # Log in to an OAuth MCP server
agentuse mcp status # Show how an agent's MCP servers sign in
agentuse mcp logout # Forget an MCP server login
agentuse models [provider] [options] # List models, aliases, and the configured default
agentuse models unpin [path] # Swap pinned model versions for version aliases
agentuse models bump [path] # Move superseded pins to the current model
agentuse skills [subcommand] [options] # List/get builtin or installed skills
agentuse doctor [--last-run] # Diagnose agent skill capability config
agentuse learnings [--json] # List an agent's stored learnings by status
agentuse learnings --path # Print where the learnings file lives
agentuse learnings tidy # Merge, sharpen, retire and make proven ones permanent
agentuse learnings undo # Restore both files to their pre-tidy state
agentuse learnings migrate --all # Move pre-0.17.0 learnings into the state directory
agentuse agents [options] # Discover and list project agents
agentuse add [options] # Add skills/agents from GitHub or local path
agentuse --version # Show version
agentuse --help # Show help
```
The `agentuse auth` command still works as a backward-compatible alias for `agentuse provider`.
## Advanced Usage
### Piping
```bash theme={"system"}
# Pipe input to agent
echo "Translate this to Spanish" | agentuse run translator.agentuse
# Pipe agent output
agentuse run generator.agentuse | tee output.txt
# Chain agents
agentuse run analyzer.agentuse < data.txt | agentuse run summarizer.agentuse
```
### Shell Integration
```bash theme={"system"}
# Bash function
agent() {
agentuse run "$1.agentuse" "${@:2}"
}
# Usage
agent translator "Hello world"
```
### Batch Processing
```bash theme={"system"}
# Process multiple files
for file in *.txt; do
agentuse run processor.agentuse < "$file" > "processed_$file"
done
# Parallel processing
find . -name "*.md" | parallel agentuse run formatter.agentuse {}
```
## Troubleshooting
Ensure AgentUse is installed globally:
```bash theme={"system"}
pnpm install -g agentuse
```
On Unix systems, you may need sudo:
```bash theme={"system"}
sudo pnpm install -g agentuse
```
If you see authentication errors, AgentUse will show specific guidance:
```bash theme={"system"}
[ERROR] No API key found for anthropic
To authenticate, run:
agentuse provider login
Or set your API key:
export ANTHROPIC_API_KEY='your-key-here'
For more options: agentuse provider --help
```
Increase timeout for long-running agents:
```bash theme={"system"}
agentuse run agent.agentuse --timeout 600
# or via environment
MAX_STEPS=2000 agentuse run agent.agentuse
```
Enable debug output:
```bash theme={"system"}
agentuse run agent.agentuse --debug
```
## Next Steps
Learn agent file format
Create your first agent
# Configuration Files
Source: https://docs.agentuse.io/reference/configuration-files
User-facing files and directories that configure AgentUse
AgentUse reads configuration from agent files, environment files, global defaults, and project or user-level extension directories.
## Quick reference
| Path | Scope | Purpose |
| - | - | - |
| `*.agentuse` | Agent | Defines an agent with YAML frontmatter and Markdown instructions |
| `.env.local` | Project | Local environment variables loaded before `.env` when present |
| `.env` | Project | Environment variables for API keys, model providers, MCP servers, and runtime behavior |
| `--env-file ` | Run command | Load a specific environment file for `agentuse run` |
| `~/.agentuse/config.json` | User | Global `agentuse serve` defaults and an `env` block of variable defaults |
| `AGENTUSE_CONFIG_DIR=/path/to/profile` | Process | Override the directory containing user-global config, env, managed projects, plugins, and skills |
| `AGENTUSE_CONFIG=/path/to/config.json` | Process | Deprecated file-level config override; compatibility only |
| `AGENTUSE_ENV=/path/to/.env` | Process | Deprecated file-level env override; compatibility only |
| `ABOUT.md` | Directory | Optional dashboard identity and description for the project or folder containing it |
| `.agentuse/plugins/*.{ts,js}` | Project | Project-local plugins |
| `$AGENTUSE_CONFIG_DIR/plugins/*.{ts,js}` | User | User-global plugins; defaults to `~/.agentuse/plugins/*.{ts,js}` |
| `.agentuse/skills/` | Project | Project-local skills |
| `$AGENTUSE_CONFIG_DIR/skills/` | User | User-global skills; defaults to `~/.agentuse/skills/` |
| `.claude/skills/` | Project | Claude ecosystem skill compatibility |
| `~/.claude/skills/` | User | Claude ecosystem skill compatibility |
| `~/.agents/skills/` | User | Shared agent skills compatibility |
| `{agent-name}.store.json` | Agent | Persistent store file for agents with store enabled |
## Agent files
Agent files use the `.agentuse` extension. They combine YAML frontmatter with Markdown instructions:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: Summarize pull requests
schedule: "0 9 * * 1"
tools:
bash:
commands:
- "gh *"
---
Review open pull requests and summarize anything blocked.
```
Common frontmatter fields include `model`, `tools`, `schedule`, `mcpServers`, `subagents`, `store`, `learning`, `sandbox`, `approval`, `channels`, `timeout`, and `maxSteps`.
See [Agent Syntax](/reference/agent-syntax) for the full schema.
Approval channels are configured separately from approval policy:
```yaml theme={"system"}
approval: true
channels:
slack:
events: [approval]
channel_id: C0123456789
```
See [Channels](/guides/channels) for event semantics and [Approval Gates](/guides/approval-gates) for the approval dashboard and API workflow.
## Environment files
AgentUse loads environment variables from the project root. Project roots are detected by walking upward from the starting directory until `.agentuse/`, `.git/`, or `package.json` is found. If none are found, the starting directory is the project root.
For `agentuse run`, `.env.local` takes priority when present, otherwise `.env` is used. You can also pass a specific file:
```bash theme={"system"}
agentuse run agent.agentuse --env-file .env.production
```
For `agentuse serve`, `-C` selects the directory whose agents are served, while the detected project root owns `.env.local`, `.env`, `.agentuse/store`, and session state. Each served project loads its own `.env.local` or `.env` in that project's worker process. Environment variables do not mix across served projects.
Use environment files for provider API keys, MCP server credentials, and runtime controls such as `MAX_STEPS`, `LOG_LEVEL`, and `AGENTUSE_TELEMETRY_DISABLED`.
Never commit `.env`, `.env.local`, or other secret-bearing environment files.
See [Environment Variables](/reference/environment-variables) for supported variables and examples.
## Global serve config
Put long-lived `agentuse serve` defaults in `~/.agentuse/config.json`:
```json theme={"system"}
{
"serve": {
"projects": [
{ "path": "~/work/projA" },
{ "id": "b", "path": "~/work/projB" }
],
"default": "projA",
"port": 12233,
"host": "127.0.0.1",
"auth": true,
"logFile": true,
"hideAgentSource": false,
"brand": { "name": "Acme Operations" },
"terms": {
"project": "workspace",
"folder": "team|teams"
}
}
}
```
Use `AGENTUSE_CONFIG_DIR=/path/to/profile` to isolate the complete configuration profile. AgentUse reads `config.json` and `.env` from that directory and uses its `projects/`, `plugins/`, and `skills/` subdirectories for user-global resources. Project paths inside `config.json` may start with `~` or `~/`.
`AGENTUSE_CONFIG` and `AGENTUSE_ENV` remain as deprecated file-level overrides for compatibility and take precedence over `AGENTUSE_CONFIG_DIR` when set. They are scheduled for removal no earlier than December 1, 2026; new integrations should use only `AGENTUSE_CONFIG_DIR`.
AgentUse runs one serve daemon at a time. Put every project that should accept `/run`, approval, and notification traffic into `serve.projects`, or pass repeated `-C` flags when starting the daemon.
| Config key | Type | Description | |
| - | - | - | - |
| `serve.projects` | array | Directories to serve agents from. Each item needs `path`; AgentUse detects the project root upward; `id` is optional | |
| `serve.default` | string | Default project id when `POST /run` omits `project` | |
| `serve.port` | number | Port to listen on | |
| `serve.host` | string | Host to bind to | |
| `serve.publicUrl` | string | Externally reachable base URL, used in approval links. A keyless daemon also accepts requests addressed to this URL's host | |
| `serve.auth` | boolean | Require API key authentication for exposed hosts | |
| `serve.logFile` | boolean | Write serve logs to a file | |
| `serve.hideAgentSource` | boolean | Hide raw `.agentuse` source in the dashboard and `/api/agents/detail`; capability summaries (model, tools, schedule) stay visible. For deployments where visitors may run and observe agents but should not read their instructions (demos, client sandboxes) | |
| `serve.brand.name` | string | Your company name, shown beside the AgentUse wordmark, in page titles, and as the installed app name (max 60 chars) | |
| `serve.terms.project` | string | Dashboard display noun for a project. Routes, API fields, and CLI output keep the technical name | |
| `serve.terms.folder` | string | Dashboard display noun for a folder. Add an explicit plural as \`singular | plural\` for irregular nouns |
CLI flags override config values:
| Config key | CLI override |
| - | - |
| `serve.projects` | `-C, --directory` replaces the configured project list |
| `serve.default` | `--default ` |
| `serve.port` | `--port ` |
| `serve.host` | `--host ` |
| `serve.publicUrl` | `--public-url ` |
| `serve.auth` | `--no-auth` sets auth to `false` |
| `serve.logFile` | `--no-log-file` sets log files to `false` |
| `serve.hideAgentSource` | `--hide-agent-source` sets it to `true` (the flag can only hide, never re-expose a config that hides) |
`AGENTUSE_API_KEY` remains env-only and is not read from config.
See [Webhooks](/guides/webhooks) and [CLI Commands](/reference/cli-commands#agentuse-serve) for serve usage.
## Directory identity with `ABOUT.md`
Place an optional `ABOUT.md` in a served project root or a directory containing
agents. The dashboard uses the file to label and describe that directory. It
does not alter agent prompts, API routes, or scheduling.
Plain Markdown becomes the longer body shown on the directory detail surface:
```md theme={"system"}
Automations owned by the Revenue Operations team.
```
Optional YAML frontmatter supplies compact display fields:
```md theme={"system"}
---
name: Revenue Operations
description: Pipeline and renewal automations
owner: Operations Platform
---
These agents reconcile CRM events and prepare renewal follow-ups.
```
Recognized frontmatter keys are `name`, `description`, and `owner`; scalar
string or numeric values are normalized for display. Unknown keys and other
value types are ignored. The body remains the longer description. AgentUse
rejects symlinked and oversized `ABOUT.md` files so directory identity cannot
disclose an unrelated local file or inflate API responses.
`serve.brand.name` labels the whole deployment; `ABOUT.md` labels one served
directory within it. Use `serve.terms` when the deployment calls projects or
folders by different nouns.
## Global env defaults
Alongside `serve`, `~/.agentuse/config.json` accepts an `env` block of environment variable defaults, mirroring the `env` key in Claude Code's `settings.json`. Use it for non-secret defaults you want applied to every run without maintaining a separate `~/.agentuse/.env` file:
```json theme={"system"}
{
"env": {
"AGENTUSE_MOCK_MODEL": "anthropic:claude-haiku-4-5"
}
}
```
Values must be strings. The block is applied at startup and **never overrides a variable that is already set**, so the precedence is:
```
shell env > ~/.agentuse/.env > config.json "env"
```
Per-command flags still win over all of these. For example, `--mock-model ` overrides `AGENTUSE_MOCK_MODEL` from any source, and `--mock` is satisfied by a mock model coming from the flag, the shell, `~/.agentuse/.env`, or the config `env` block.
Keep secrets (like `AGENTUSE_API_KEY` and provider API keys) in an environment file rather than `config.json`, which is plain non-secret configuration.
## Model defaults and aliases
A `models` block in `~/.agentuse/config.json` sets the model used by agent files that omit `model`, and names models that agent files reference as `@name`:
```json theme={"system"}
{
"models": {
"default": "anthropic:claude-sonnet",
"aliases": {
"fast": "anthropic:claude-haiku",
"smart": "anthropic:claude-opus",
"cheap-dev": "openai:gpt-mini:dev",
"judgment": {
"candidates": ["anthropic:claude-opus", "openai:gpt"],
"cooldown": "5m"
}
}
}
}
```
```yaml theme={"system"}
---
model: "@fast"
---
```
* **`default`** applies to any agent file with no `model:` field. `AGENTUSE_MODEL` overrides it, and an explicit `model:` in the file overrides both.
* **`aliases`** keys are alphanumeric with hyphens or underscores, referenced with the `@` sigil (define `fast`, write `@fast`). The `@` is required in the reference because a bare name is already a valid OpenAI model id.
* A string value may be a concrete id, a [version alias](/reference/models#version-aliases), another `@name`, or any of those with an `:env` auth suffix.
* An object value defines ordered fallback `candidates`. AgentUse tries the next candidate on a transient first-request failure (rate limit, timeout, provider 5xx, or transport failure) or when the candidate cannot be authenticated at all (no login, an OAuth token that will not refresh, a 401/403), and only if the model has not produced output or invoked a tool in the current execution segment. The resolved order is persisted so the same policy remains available after an approval resume.
* Optional `cooldown` is a duration string such as `"30s"` or `"5m"`. A concrete model that just failed this way is skipped by new runs in the same process until the cooldown expires. Cooldowns are in memory: restarting `agentuse serve` or starting a separate CLI process resets them.
Aliases are resolved when the agent file is parsed. A fallback alias keeps its ordered concrete candidates until execution. Session logs, cost accounting, and context limits record the concrete model that actually ran. A suspended run first resumes on its last selected model, even if the alias has since changed, and can advance through the remaining persisted candidates if that resumed segment fails before producing new output or invoking a tool.
To point a repo at its own aliases rather than your user-global ones, put `config.json` in a dedicated directory and set `AGENTUSE_CONFIG_DIR` to that directory.
Run `agentuse models` to see every alias and what it currently resolves to.
## Plugins
Loose plugins are TypeScript or JavaScript modules loaded from these directories:
1. `.agentuse/plugins/*.{ts,js}`
2. `$AGENTUSE_CONFIG_DIR/plugins/*.{ts,js}` (defaults to `~/.agentuse/plugins/*.{ts,js}`)
Project plugins load before user-global plugins.
Installed global packages are recorded under `$AGENTUSE_DATA_DIR/plugins`, which defaults to `~/.local/share/agentuse/plugins`. Plugins installed with `agentuse plugins install -l` live under `.agentuse/packages` and are recorded in `.agentuse/plugins.json`.
See [Plugins](/guides/plugins) for the plugin API.
## Skills
Skills are reusable instruction packs stored as `SKILL.md` files. AgentUse discovers skills in this order:
1. `.agentuse/skills/`
2. `$AGENTUSE_CONFIG_DIR/skills/` (defaults to `~/.agentuse/skills/`)
3. `.claude/skills/`
4. `~/.claude/skills/`
5. `~/.agents/skills/`
Use `.agentuse/skills/` for project-specific skills and `$AGENTUSE_CONFIG_DIR/skills/` for personal skills shared across projects. The latter defaults to `~/.agentuse/skills/`. The `.claude/skills/` locations provide compatibility with existing Claude skills, while `~/.agents/skills/` supports the shared agent-skills convention. Symlinked skill directories and `SKILL.md` files are supported; dangling links are skipped and circular directory links are ignored safely.
See [Skills](/guides/skills) for authoring and discovery details.
## Generated files and data locations
These files are generated by features rather than hand-written as primary configuration:
| Path | Created by | Purpose |
| - | - | - |
| `{agent-name}.store.json` | Store | Stores persistent key-value data for the agent |
| `.agentuse/sandbox/` | Sandbox | Stores sandbox-related working data |
| `.agentuse/benchmark/` | Benchmark | Stores local benchmark suites and results |
| `$AGENTUSE_DATA_DIR/` | AgentUse runtime | Credentials, sessions, learnings, schedules, registry, logs, push, telemetry, and update state; defaults to `~/.local/share/agentuse/` |
Configuration and durable application data have separate roots. `AGENTUSE_CONFIG_DIR` moves user-controlled configuration; `AGENTUSE_DATA_DIR` moves AgentUse-owned data. `XDG_DATA_HOME` remains a compatible base-directory fallback. Isolated test or development servers should set the two AgentUse-specific variables.
State that a run generates rather than a person writes lives outside the project, under a per-project directory keyed by a digest of the git root:
```
$AGENTUSE_DATA_DIR/project/{project-hash}/
├── session/ # execution logs
├── learnings/ # agent learnings, one file per agent
└── consolidations/ # undo snapshots for `agentuse learnings tidy`
```
Learnings moved here in v0.17.0; they used to sit beside the agent file as `{agent-file}.learnings.md`, where every run rewrote them into your working tree. `agentuse learnings --path` prints the new location and `agentuse learnings migrate --all` moves existing files into it.
See [Learning](/guides/learning), [Store](/guides/store), [Sandbox](/guides/sandbox), and [Session Storage](/reference/session-storage) for details.
# Environment Variables
Source: https://docs.agentuse.io/reference/environment-variables
Environment variables used by AgentUse
## Configuration Profile
Directory containing AgentUse's user-controlled `config.json`, `.env`,
managed `projects/`, user-global `plugins/`, and user-global `skills/`. Set
this together with `AGENTUSE_DATA_DIR` when isolating a test or development
server.
```bash theme={"system"}
export AGENTUSE_CONFIG_DIR="/tmp/agentuse-test/config"
export AGENTUSE_DATA_DIR="/tmp/agentuse-test/data"
```
The older `AGENTUSE_CONFIG` and `AGENTUSE_ENV` file-level overrides are
deprecated compatibility controls. When present they take precedence for
their respective file and are scheduled for removal no earlier than
December 1, 2026.
## API Configuration
These environment variables are required for authenticating with AI providers.
API key for Anthropic Claude models.
```bash theme={"system"}
export ANTHROPIC_API_KEY="sk-ant-api03-..."
```
Claude subscription OAuth is provided by the shortlisted
[Claude Code Subscription plugin](/guides/plugins#curated-provider-plugins).
Long-lived Claude subscription token used by the shortlisted Claude Code
Subscription plugin. It is not used by the built-in Anthropic API transport.
Install the plugin before using this variable:
```bash theme={"system"}
agentuse plugins install cb7337/agentuse-claude-code-provider@v0.1.0
export CLAUDE_CODE_OAUTH_TOKEN="your-access-token"
```
API key for OpenAI GPT models.
```bash theme={"system"}
export OPENAI_API_KEY="sk-proj-..."
```
API key for OpenRouter service.
```bash theme={"system"}
export OPENROUTER_API_KEY="sk-or-v1-..."
```
API key for OpenCode Go open coding models.
```bash theme={"system"}
export OPENCODE_GO_API_KEY="..."
```
Optional base URL override for OpenCode Go. Defaults to `https://opencode.ai/zen/go/v1`.
```bash theme={"system"}
export OPENCODE_GO_BASE_URL="https://opencode.ai/zen/go/v1"
```
AWS access key ID for Amazon Bedrock authentication (SigV4). Used together with `AWS_SECRET_ACCESS_KEY` and `AWS_REGION`.
```bash theme={"system"}
export AWS_ACCESS_KEY_ID="AKIA..."
```
AWS secret access key for Amazon Bedrock authentication (SigV4).
```bash theme={"system"}
export AWS_SECRET_ACCESS_KEY="..."
```
AWS region for Amazon Bedrock API calls (e.g. `us-east-1`). Falls back to `AWS_DEFAULT_REGION` if unset. Required when using Bedrock.
```bash theme={"system"}
export AWS_REGION="us-east-1"
```
Optional AWS session token for temporary credentials (e.g. STS / assumed roles) when using Amazon Bedrock.
```bash theme={"system"}
export AWS_SESSION_TOKEN="..."
```
Bedrock API key (Bearer token). When set, used instead of AWS SigV4 authentication.
```bash theme={"system"}
export AWS_BEARER_TOKEN_BEDROCK="..."
```
AWS named profile from `~/.aws/credentials` / `~/.aws/config`. Used when no static keys or Bearer token are set: the SDK credential provider chain resolves SSO cache, assumed roles, instance metadata, etc.
```bash theme={"system"}
export AWS_REGION=eu-west-1
export AWS_PROFILE=my-bedrock-profile
```
## Custom API Key Suffixes
You can use multiple API keys by adding suffixes:
```bash theme={"system"}
# For development environment
export ANTHROPIC_API_KEY_DEV="sk-ant-api03-dev..."
export OPENAI_API_KEY_DEV="sk-proj-dev..."
# For production environment
export ANTHROPIC_API_KEY_PROD="sk-ant-api03-prod..."
export OPENAI_API_KEY_PROD="sk-proj-prod..."
```
Then reference them in your agent:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5:dev # Uses ANTHROPIC_API_KEY_DEV
---
```
## Serve Mode
API key for authenticating requests to the serve mode HTTP server.
Required when binding to exposed hosts (not `127.0.0.1` or `localhost`).
The daemon reads it once at startup and removes it from its environment, so bash commands, MCP servers, and skill scripts that agents launch do not inherit it.
```bash theme={"system"}
export AGENTUSE_API_KEY="your-secret-key"
agentuse serve --host 0.0.0.0
```
Clients authenticate via Bearer token:
```bash theme={"system"}
curl -X POST http://server:12233/api/run \
-H "Authorization: Bearer your-secret-key" \
-d '{"agent": "my-agent.agentuse"}'
```
GitHub repository (`owner/name`) that the "Report to AgentUse" link on a
changeset review points at. The reviser sets it when a no-change diagnosis
blames the AgentUse runtime rather than the agent. Point it at a fork or an
internal tracker when your team triages framework bugs elsewhere.
```bash theme={"system"}
export AGENTUSE_ISSUE_REPO="my-org/agentuse-fork"
```
Heap size, in MB, at which an idle per-project worker is retired and replaced.
```bash theme={"system"}
export AGENTUSE_WORKER_RECYCLE_MB="300"
```
A worker bank starts around 130MB of peak heap and settles at roughly 350-450MB once it has executed runs, so a long-lived daemon otherwise holds that memory indefinitely. When an idle worker is over the threshold it is retired through the same release path used at shutdown: runs already in flight finish in the old worker while a replacement starts serving immediately. A worker is only ever recycled while idle, and never within 2 minutes of starting. Set `0` to disable recycling.
Set to `0` to restore the old kill-on-shutdown behavior. By default `agentuse serve` releases its workers on shutdown instead of killing them, so a `pm2` or `systemd` restart does not destroy runs that are mid-flight.
```bash theme={"system"}
export AGENTUSE_RELEASE_WORKERS="0"
```
Hard deadline, in seconds, for a released worker to exit after the daemon goes away. Defaults to the longest in-flight run's own timeout plus 10 minutes of grace.
```bash theme={"system"}
export AGENTUSE_RELEASE_BACKSTOP_SECONDS="1800"
```
## Approval Gates
Slack bot token used to post and update channel messages when `channels.slack` listens for `approval`, `completion`, or `failure`. The app needs the `chat:write` bot scope, and the bot must be in the target channel unless you also grant `chat:write.public` for public channels.
```bash theme={"system"}
export SLACK_BOT_TOKEN="xoxb-..."
```
Optional Slack app-level token used for Socket Mode approval actions in Slack. Web approval pages and channel-only Slack messages do not require this token. If set, the app-level token needs `connections:write`; plain thread-reply comments also require Slack message event subscriptions and the relevant channel history scopes.
```bash theme={"system"}
export SLACK_APP_TOKEN="xapp-..."
```
Default Slack channel id for Slack channels. Agents can override this with `channels.slack.channel_id`.
```bash theme={"system"}
export SLACK_APPROVAL_CHANNEL="C0123456789"
```
Fallback public base URL used to build approval review links. Its host also joins the keyless daemon's allowed request hosts. Prefer `agentuse serve --public-url ...` or `serve.publicUrl` for hosted deployments.
```bash theme={"system"}
export AGENTUSE_RESUME_PUBLIC_URL="https://agentuse.mycompany.com"
```
## Behavior Control
Model used by agent files that omit `model:`.
```bash theme={"system"}
export AGENTUSE_MODEL="anthropic:claude-sonnet"
```
Accepts anything a `model:` field accepts: a concrete id, a [version alias](/reference/models#version-aliases), a configured `@name`, or any of those with an `:env` auth suffix.
**Precedence:** an explicit `model:` in the agent file wins; otherwise this variable wins over `models.default` in the AgentUse config. With none of the three set, an agent file without `model:` fails to parse.
Override the maximum number of conversation steps (LLM generation cycles) an agent can take.
Default: 100
```bash theme={"system"}
export MAX_STEPS="200"
```
**Precedence:** This environment variable overrides the `maxSteps` value in agent YAML files.
This prevents infinite loops and controls cost by limiting the number of LLM calls. Each step typically involves an LLM generation with potential tool calls.
The default was reduced from 1000 to 100 for better cost protection. Most agents complete successfully within 100 steps.
Default timeout in seconds for individual MCP tool calls.
Default: 60
```bash theme={"system"}
export MCP_TOOL_TIMEOUT="120"
```
**Precedence:** A server's `toolTimeout` in agent YAML overrides this variable; this variable overrides the built-in 60-second default.
## Code Mode
Code Mode is enabled by default. Set this to `0` to omit `code_exec` from
normal runs. The policy is inherited by recursive subagents and serve worker
processes, which makes it suitable for controlled before-and-after tests or
emergency rollback. This is a runtime switch only; do not add it to an
agent's frontmatter.
```bash theme={"system"}
AGENTUSE_CODE_MODE=0 agentuse run agent.agentuse
AGENTUSE_CODE_MODE=0 agentuse serve
```
The CLI equivalents are `agentuse run --no-code-mode` and
`agentuse serve --no-code-mode`.
## Mock Mode (Testing)
Mock all tool outputs with the LLM instead of executing them. Mirror the `--mock` flags on
`agentuse run`; see [Testing with Mocked Tools](/reference/cli-commands#testing-with-mocked-tools).
`1` to mock all tool outputs (no real bash/filesystem/MCP/store side effects). Same as `--mock`. Requires `AGENTUSE_MOCK_MODEL`.
Model that generates mock outputs. **Required** whenever mock mode is on (same as `--mock-model`). Not defaulted to the agent's model on purpose: mock fires an LLM call per tool result, and running that on the agent's premium, rate-limited token caused opaque `429`s.
Use the **lowest-end model you can reach** here: mocking only fabricates a plausible tool result, not real reasoning, so a small fast model is plenty and keeps cost and rate-limit pressure low. Good picks: `anthropic:claude-haiku-4-5`, `openai:gpt-5.4-nano`, or `openrouter:deepseek/deepseek-v4-flash`.
Set it for one run with `--mock-model`, or as a global default in the shell, `~/.agentuse/.env`, or the [`env` block of `~/.agentuse/config.json`](/reference/configuration-files#global-env-defaults). `--mock-model` overrides whichever source supplies it.
What mock mode covers. Unset (or `all`) mocks every tool result, same as `--mock`. `gated` mocks only bash commands matching the agent's `tools.bash.gated` patterns and leaves every other tool real, same as `agentuse test --scope gated`. Only read when mock mode is on.
Resolve the `await_human` approval gate deterministically instead of suspending (mock mode only). Same as `--mock-approval`. Values: `approve` (also `1`/`true`), `reject`, or `comment:`. An approve grants the gated-command lease from the gate's `changes[]` exactly like a real reviewer approval; a reject seals the gate (terminal), and a comment forces the revise-and-re-gate branch on the first gate then approves the re-gate.
## Context Management
Enable or disable automatic context compaction when approaching model limits.
Default: true (enabled)
```bash theme={"system"}
# Disable context compaction
export CONTEXT_COMPACTION="false"
```
When enabled, AgentUse automatically compacts older messages when context approaches the model's token limit.
Percentage of context limit to trigger compaction.
Default: 0.7 (70%)
```bash theme={"system"}
export COMPACTION_THRESHOLD="0.8" # Trigger at 80%
```
Must be a decimal between 0 and 1.
Number of recent messages to preserve during compaction.
Default: 3
```bash theme={"system"}
export COMPACTION_KEEP_RECENT="5" # Keep last 5 messages
```
These messages are never compacted to maintain conversation flow.
Minimum active-context size that triggers opportunistic compaction at an approval gate.
Default: 64000
```bash theme={"system"}
export APPROVAL_COMPACTION_MIN_TOKENS="32000"
```
This is separate from `COMPACTION_THRESHOLD`: a 64k-token context may be far
below a large model's window, but still expensive to resend after a human
approval pause. Set to `0` to disable approval-boundary compaction while
keeping normal model-limit compaction enabled.
Minimum active-context size that triggers opportunistic compaction between LLM
steps after the first tool call.
Default: 64000
```bash theme={"system"}
export STEP_COMPACTION_MIN_TOKENS="128000"
```
This enables split-turn compaction for long autonomous runs: older context can
be summarized before the next model call even when the full model window is not
close to exhausted. Set to `0` to disable step-boundary compaction while
keeping approval-boundary and model-limit compaction enabled.
## Tool Output
Large tool results are re-sent to the model on every subsequent step. AgentUse stores oversized direct JSON and text results outside model context and returns a queryable handle instead. Bash keeps a larger bounded canonical capture for that result store, with the complete stream saved as a session artifact if the capture ceiling is crossed.
Maximum serialized size of a direct JSON or text response returned inline. Larger results become a reusable `resultId` handle with a partial `preview` and jq-style `omitted` map, and can be narrowed with the `results` tool.
Default: 10240 (10KB)
```bash theme={"system"}
export AGENTUSE_TOOL_INLINE_RESULT_BYTES="16384" # 16KB
```
Maximum serialized size returned inline by one `results` tool query. Queries above this limit ask for a narrower selection and never create another result handle.
Default: 20480 (20KB)
```bash theme={"system"}
export AGENTUSE_RESULT_QUERY_BYTES="32768" # 32KB
```
Maximum canonical output retained by the built-in `bash` accumulator for reusable results. Output over this limit is reduced to a head + tail slice and the complete stream is saved as a session artifact; AgentUse does not issue a reusable `resultId` for that incomplete capture.
Default: 4194304 (4MB)
```bash theme={"system"}
export AGENTUSE_BASH_CAPTURE_BYTES="8388608" # 8MB
```
Legacy general tool-output limit. It remains the fallback for Bash canonical capture and the inline result limit when their dedicated variables are unset, preserving existing configurations. Prefer `AGENTUSE_BASH_CAPTURE_BYTES` and `AGENTUSE_TOOL_INLINE_RESULT_BYTES` for independent control.
Default: 30720 (30KB)
```bash theme={"system"}
export AGENTUSE_TOOL_MAX_OUTPUT_BYTES="61440" # 60KB
```
Fraction of a truncated output budget kept as the head; the remainder is kept as the tail. Errors and context often appear early, while the most recent output appears at the end, so both ends are preserved.
Default: 0.4 (40% head / 60% tail)
```bash theme={"system"}
export AGENTUSE_TOOL_OUTPUT_HEAD_RATIO="0.5" # even split
```
Must be a decimal between 0 and 1.
Default number of lines `read_file` returns when no explicit `limit` is given (and the truncation cap for file reads).
Default: 2000
```bash theme={"system"}
export AGENTUSE_TOOL_MAX_LINES="5000"
```
Per-line character cap for `read_file` output. Longer lines are truncated with a `... (truncated)` suffix.
Default: 2000
```bash theme={"system"}
export AGENTUSE_TOOL_MAX_LINE_LENGTH="4000"
```
Prefer not generating bloat in the first place over raising these caps. For example, use `git diff --stat` instead of a full `git diff` of high-churn files. Truncation is a safety net, not a substitute for asking the tool for less.
## Logging and Debug
Set the logging level for AgentUse output.
Default: INFO
```bash theme={"system"}
export LOG_LEVEL="DEBUG" # Available: DEBUG, INFO, WARN, ERROR
```
Controls which messages are displayed during execution.
Enable debug logging and verbose output.
Default: false
```bash theme={"system"}
export DEBUG="true" # or DEBUG="1"
```
Shows detailed execution information, tool calls, and internal state.
## Telemetry
Disable all anonymous telemetry, including CLI, daemon, execution, and bundled
dashboard telemetry. AgentUse records installation and first-execution
lifecycle events, execution metadata, and a fixed top-level dashboard page
category. The browser sends that category only to its local AgentUse daemon,
which batches delivery; it does not contact PostHog directly. Server telemetry reports only the kind of bind address (`host_class`: `loopback`, `any`, or `other`), never the host itself. No prompts,
code, or file paths are ever collected.
Default: false (telemetry enabled)
```bash theme={"system"}
export AGENTUSE_TELEMETRY_DISABLED=true
```
## Update Checks
Disable the daily npm registry check and all CLI/Web UI update reminders.
Update checks are cached locally, run off the command's critical path, and
are also disabled automatically in CI, local development builds, and `npx`
cache executions. Interactive CLI reminders appear at most once per version
every seven days and are suppressed for non-TTY, `--quiet`, and `--json`
output. The dashboard keeps its dismissal per browser and version.
```bash theme={"system"}
export AGENTUSE_UPDATE_CHECK_DISABLED=true
```
## Storage
Exact directory containing AgentUse-owned durable data: provider credentials,
installed global plugins, sessions, learnings, schedules, server registry and
logs, push state, telemetry identity, and update state.
```bash theme={"system"}
export AGENTUSE_DATA_DIR="/custom/agentuse-data"
```
AgentUse does not append another `agentuse/` component to this path. This
variable takes precedence over `XDG_DATA_HOME`.
Standards-compatible fallback base directory. AgentUse uses
`$XDG_DATA_HOME/agentuse` only when `AGENTUSE_DATA_DIR` is unset. Default XDG
base: `~/.local/share`.
```bash theme={"system"}
export XDG_DATA_HOME="/custom/data/path"
```
Everything a run generates is stored per project, under the resolved
AgentUse data directory:
```
$AGENTUSE_DATA_DIR/project/{git-hash}/
├── session/ # execution logs
├── learnings/ # agent learnings
└── consolidations/ # undo snapshots for `agentuse learnings tidy`
```
For a fully isolated development daemon, set `AGENTUSE_DATA_DIR` and
`AGENTUSE_CONFIG_DIR`. Existing XDG-based integrations remain compatible.
See [Session Logs](/guides/session-logs) and [Learning](/guides/learning) for more details.
## Development Variables
For local development with self-signed certificates (HTTPS testing).
```bash theme={"system"}
# Only for development - allows self-signed certs
export NODE_TLS_REJECT_UNAUTHORIZED="0"
```
Never use this in production. It disables SSL certificate verification.
## MCP Server Environment Variables
**Security by Design**: AgentUse intentionally prevents hardcoding secrets in `.agentuse` files. All sensitive values must come from environment variables, keeping your secrets secure and out of version control.
### The Security Model
MCP servers can access environment variables through two fields:
* **`requiredEnvVars`**: Variables that MUST exist or the agent fails immediately
* **`allowedEnvVars`**: Variables that are passed through if they exist (optional)
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
notion:
command: "pnpx"
args: ["-y", "@notionhq/notion-mcp-server"]
requiredEnvVars:
- NOTION_API_KEY # Fails immediately if missing
allowedEnvVars:
- NOTION_DEBUG_MODE # Optional, warns if missing
- NOTION_WORKSPACE_ID # Optional, warns if missing
---
```
### Why This Design?
1. **No Secrets in Code**: `.agentuse` files are often committed to version control
2. **Clear Requirements**: Developers know exactly what env vars are needed
3. **Early Failure**: Missing required vars fail fast with clear error messages
4. **Security Allowlist**: Only explicitly allowed vars are passed to MCP servers
### Setting Environment Variables
Create a `.env` file in your project root:
```bash theme={"system"}
# .env
NOTION_API_KEY=secret_abc123
GITHUB_TOKEN=ghp_xyz789
OPENAI_API_KEY=sk-proj-...
```
AgentUse automatically loads `.env` files from the project root (detected via `.git/`, `.agentuse/`, or `package.json`).
**Override Options:**
```bash theme={"system"}
# Use a specific .env file
agentuse run agent.agentuse --env-file .env.production
# Run from a different directory
agentuse run agent.agentuse -C /path/to/project
```
Add `.env` to your `.gitignore` to prevent committing secrets!
Export variables in your shell session:
```bash theme={"system"}
export NOTION_API_KEY="secret_abc123"
export GITHUB_TOKEN="ghp_xyz789"
# Then run your agent
agentuse run my-agent.agentuse
```
For permanent setup, add to `~/.zshrc` or `~/.bashrc`:
```bash theme={"system"}
# ~/.zshrc
export NOTION_API_KEY="secret_abc123"
export GITHUB_TOKEN="ghp_xyz789"
```
Pass variables directly when running:
```bash theme={"system"}
NOTION_API_KEY="secret_abc123" agentuse run my-agent.agentuse
```
Useful for CI/CD or one-time runs.
For production, use secret managers:
```bash theme={"system"}
# AWS Secrets Manager
export NOTION_API_KEY=$(aws secretsmanager get-secret-value \
--secret-id notion-api-key --query SecretString --output text)
# 1Password CLI
export NOTION_API_KEY=$(op read "op://vault/notion/api-key")
# HashiCorp Vault
export NOTION_API_KEY=$(vault kv get -field=api_key secret/notion)
```
### Error Messages
AgentUse provides clear, actionable error messages:
```bash theme={"system"}
# Missing required variable
Error: Missing required environment variables for MCP server 'notion': NOTION_API_KEY
Please set these in your .env file or export them in your shell.
# Missing optional variable (warning only)
[WARN] Optional environment variable 'NOTION_DEBUG_MODE' not set for server 'notion'
# Connection failure with hint
Failed to connect to MCP server 'github'
Note: The following optional environment variables are not set: GITHUB_TOKEN
If this server requires these variables, please set them in your .env file.
```
### Complete Example
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
# API-based service requiring authentication
notion:
command: "pnpx"
args: ["-y", "@notionhq/notion-mcp-server"]
requiredEnvVars:
- NOTION_API_KEY # Must be set or fails
allowedEnvVars:
- NOTION_DEBUG # Optional debug flag
# Database connection
postgres:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-postgresql"]
requiredEnvVars:
- DATABASE_URL # Required connection string
allowedEnvVars:
- PG_STATEMENT_TIMEOUT # Optional timeout
- PG_POOL_SIZE # Optional pool config
# Local filesystem (no auth needed)
filesystem:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "./data"]
# No env vars needed for local filesystem
---
```
With `.env` file:
```bash theme={"system"}
# Required vars (agent won't start without these)
NOTION_API_KEY=secret_abc123
DATABASE_URL=postgresql://user:pass@localhost/mydb
# Optional vars (agent works without these)
NOTION_DEBUG=true
PG_POOL_SIZE=20
```
## Using .env Files
For a full overview of user-facing configuration files and directories, see [Configuration Files](/reference/configuration-files).
AgentUse automatically loads `.env` files if present in your project directory:
```bash theme={"system"}
# .env
ANTHROPIC_API_KEY=sk-ant-api03-...
OPENAI_API_KEY=sk-proj-...
OPENROUTER_API_KEY=sk-or-v1-...
OPENCODE_GO_API_KEY=...
GITHUB_TOKEN=ghp_...
DATABASE_URL=postgresql://user:pass@localhost/db
# Behavior control
MAX_STEPS=500
# Context management
CONTEXT_COMPACTION=true
COMPACTION_THRESHOLD=0.7
COMPACTION_KEEP_RECENT=3
APPROVAL_COMPACTION_MIN_TOKENS=64000
STEP_COMPACTION_MIN_TOKENS=64000
# Logging and debug
LOG_LEVEL=INFO
DEBUG=false
# Telemetry (opt-out)
AGENTUSE_TELEMETRY_DISABLED=false
```
Never commit `.env` files to version control. Add them to `.gitignore`.
## Priority Order
Environment variables are loaded in this order (later overrides earlier):
1. System environment variables
2. `.env` file in current directory
3. Command-line environment variables
Example:
```bash theme={"system"}
# This overrides any existing MAX_STEPS value
MAX_STEPS=100 agentuse run agent.agentuse
```
## Security Best Practices
### Store Secrets Securely
Never hardcode API keys in agent files:
```yaml theme={"system"}
# ❌ Bad - Would be insecure (but AgentUse doesn't allow this)
mcpServers:
github:
env:
GITHUB_TOKEN: "ghp_actualTokenHere" # Not supported by design!
# ✅ Good - Use environment variable allowlist
mcpServers:
github:
command: "pnpx"
args: ["-y", "@modelcontextprotocol/server-github"]
requiredEnvVars:
- GITHUB_TOKEN # Must be in .env or shell environment
```
### Use .gitignore
Always exclude sensitive files:
```gitignore theme={"system"}
# Environment files
.env
.env.local
.env.*.local
# API keys
*.key
*.pem
```
### Validate Required Variables
For MCP servers that require specific environment variables, they will fail with clear error messages if the variables are not set.
## Troubleshooting
Verify the environment variable is set:
```bash theme={"system"}
echo $ANTHROPIC_API_KEY
```
If empty, set it:
```bash theme={"system"}
export ANTHROPIC_API_KEY="your-key-here"
```
Or use the auth command:
```bash theme={"system"}
agentuse auth login
```
Check which key is being used:
```bash theme={"system"}
agentuse auth list
```
When the Claude Code Subscription plugin is installed, subscription OAuth
takes priority over the built-in Anthropic API-key transport.
Ensure you're setting it before running the agent:
```bash theme={"system"}
export MAX_STEPS=100
agentuse run agent.agentuse
# Or inline:
MAX_STEPS=100 agentuse run agent.agentuse
```
## Next Steps
Set up model providers and API keys
Configure MCP servers
# Model Reference
Source: https://docs.agentuse.io/reference/models
Recommended AI models for AgentUse
# Model Reference
This page lists recommended models for AgentUse, organized by provider.
> **Note**: Other models from these providers may also work. These are the ones we recommend and test against.
> **Auto-generated**: Run `pnpm generate:models` to update.
## Quick Reference
**Default models:**
* **Anthropic**: `anthropic:claude-sonnet-5-5` (balanced performance)
* **OpenAI**: `openai:gpt-5.6` (general-purpose GPT)
* **OpenRouter**: `openrouter:z-ai/glm-5.3` (open source)
* **OpenCode Go**: `opencode-go:gpt-6-luna` (open coding models)
* **Amazon Bedrock**: `bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0`
## Version Aliases
Leave the version off a model id and you get whichever release is current, so an
agent file does not need editing every time a new model ships:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet # -> anthropic:claude-sonnet-5-5 today
---
```
Aliases follow the lineup below, which is refreshed per AgentUse release. An id
that exists for real always wins, so nothing you pin can be reinterpreted.
| Alias | Currently resolves to |
| - | - |
| `anthropic:claude-opus` | `anthropic:claude-opus-5-5` |
| `anthropic:claude-haiku` | `anthropic:claude-haiku-5-5` |
| `anthropic:claude-sonnet` | `anthropic:claude-sonnet-5-5` |
| `anthropic:claude-fable` | `anthropic:claude-fable-5-1` |
| `openai:gpt-sol` | `openai:gpt-6.1-sol` |
| `openai:gpt-luna` | `openai:gpt-6-luna` |
| `openai:gpt-astra` | `openai:gpt-6-astra` |
| `openai:gpt` | `openai:gpt-5.6` |
| `openai:gpt-terra` | `openai:gpt-5.6-terra` |
| `openai:gpt-pro` | `openai:gpt-5.5-pro` |
| `openai:gpt-nano` | `openai:gpt-5.4-nano` |
| `openai:gpt-mini` | `openai:gpt-5.4-mini` |
| `openai:gpt-codex` | `openai:gpt-5.3-codex` |
| `openai:gpt-codex-spark` | `openai:gpt-5.3-codex-spark` |
| `openai:gpt-chat-latest` | `openai:gpt-5.3-chat-latest` |
| `openrouter:z-ai/glm` | `openrouter:z-ai/glm-5.3` |
| `openrouter:z-ai/glm-prime` | `openrouter:z-ai/glm-5.3-prime` |
| `openrouter:z-ai/glm-flash` | `openrouter:z-ai/glm-5.3-flash` |
| `openrouter:z-ai/glm-flashx` | `openrouter:z-ai/glm-5.3-flashx` |
| `openrouter:z-ai/glm-turbo` | `openrouter:z-ai/glm-5v-turbo` |
| `openrouter:x-ai/grok` | `openrouter:x-ai/grok-4.7` |
| `openrouter:deepseek/deepseek-pro` | `openrouter:deepseek/deepseek-v4-pro` |
| `openrouter:deepseek/deepseek-flash` | `openrouter:deepseek/deepseek-v4-flash` |
| `openrouter:qwen/qwen-max` | `openrouter:qwen/qwen3.8-max-0902` |
| `openrouter:google/gemini-flash` | `openrouter:google/gemini-3.8-flash` |
| `openrouter:google/gemini-pro-preview` | `openrouter:google/gemini-3.1-pro-preview` |
| `openrouter:minimax/minimax` | `openrouter:minimax/minimax-m3` |
| `openrouter:moonshotai/kimi` | `openrouter:moonshotai/kimi-k3` |
| `openrouter:google/gemini-flash-preview` | `openrouter:google/gemini-3-flash-preview` |
| `opencode-go:gpt-luna` | `opencode-go:gpt-6-luna` |
| `opencode-go:glm` | `opencode-go:glm-5.3` |
| `opencode-go:glm-flash` | `opencode-go:glm-5.3-flash` |
| `opencode-go:grok` | `opencode-go:grok-4.7` |
| `opencode-go:hy-preview` | `opencode-go:hy4-preview` |
| `opencode-go:deepseek-pro` | `opencode-go:deepseek-v4-pro` |
| `opencode-go:qwen-max` | `opencode-go:qwen3.8-max` |
| `opencode-go:qwen-flash` | `opencode-go:qwen3.8-flash` |
| `opencode-go:qwen-plus` | `opencode-go:qwen3.7-plus` |
| `opencode-go:kimi` | `opencode-go:kimi-k3` |
| `opencode-go:minimax` | `opencode-go:minimax-m3` |
| `opencode-go:kimi-code` | `opencode-go:kimi-k2.7-code` |
| `opencode-go:mimo-pro` | `opencode-go:mimo-v2.6-pro` |
| `opencode-go:mimo` | `opencode-go:mimo-v2.5` |
Run `agentuse models` to see what each alias resolves to on your install, and
`agentuse models unpin` to convert pinned ids in your agent files into aliases.
To name your own, add a `models.aliases` block to `~/.agentuse/config.json` and
reference it with the `@` sigil (see [Configuration Files](/reference/configuration-files#models)):
```json theme={"system"}
{ "models": { "default": "anthropic:claude-sonnet", "aliases": { "fast": "anthropic:claude-haiku" } } }
```
```yaml theme={"system"}
---
model: "@fast"
---
```
Aliases can include a reasoning preset. Use `reasoning`, the same field as
agent frontmatter, and give each fallback its own setting:
```json theme={"system"}
{
"models": {
"aliases": {
"astra-high": { "model": "openai:gpt-6-astra", "reasoning": "high" },
"deep": {
"candidates": [
"@astra-high",
{ "model": "anthropic:claude-opus", "reasoning": "high" },
{ "model": "openai:gpt", "reasoning": "medium" }
],
"cooldown": "1m"
}
}
}
}
```
Select this chain with `model: "@deep"`. A candidate's explicit reasoning takes
precedence over agent frontmatter. Candidates without a preset use the agent's
reasoning setting, or the model default when that is omitted. Effort is never
inherited from the previous candidate. Existing model-specific reasoning
compatibility rules still apply.
Presets support `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.
`agentuse models` shows configured effort alongside each resolved candidate.
The resolved settings are captured with the session for approval resume and
with run-wide model overrides. If a preset references another fallback alias,
its reasoning override applies only to that alias's primary candidate. Repeating
a concrete model with conflicting reasoning settings is a configuration error.
Named aliases may also define ordered fallback candidates and an in-memory
cooldown. See [Model defaults and aliases](/reference/configuration-files#model-defaults-and-aliases).
## Recommended Models
### Anthropic
| Model ID | Name | Input Context | Output | Capabilities |
| - | - | - | - | - |
| `anthropic:claude-opus-5-5` | Claude Opus 5.5 | 1,000,000 | 128,000 | Reasoning, Vision, Tools |
| `anthropic:claude-haiku-5-5` | Claude Haiku 5.5 | 1,000,000 | 128,000 | Reasoning, Vision, Tools |
| `anthropic:claude-sonnet-5-5` | Claude Sonnet 5.5 | 1,000,000 | 128,000 | Reasoning, Vision, Tools |
| `anthropic:claude-fable-5-1` | Claude Fable 5.1 | 1,000,000 | 128,000 | Reasoning, Vision, Tools |
### OpenAI
| Model ID | Name | Input Context | Output | Capabilities |
| - | - | - | - | - |
| `openai:gpt-6.1-sol` | GPT-6.1 Sol | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-6-luna` | GPT-6 Luna | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-6-astra` | GPT-6 Astra | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.6` | GPT-5.6 | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.6-terra` | GPT-5.6 Terra | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.5-pro` | GPT-5.5 Pro | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.4-nano` | GPT-5.4 nano | 272,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.4-mini` | GPT-5.4 mini | 272,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.3-codex` | GPT-5.3 Codex | 272,000 | 128,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.3-codex-spark` | GPT-5.3 Codex Spark | 100,000 | 32,000 | Reasoning, Vision, Tools |
| `openai:gpt-5.3-chat-latest` | GPT-5.3 Chat (latest) | 128,000 | 16,384 | Vision, Tools |
### OpenRouter
| Model ID | Name | Input Context | Output | Capabilities |
| - | - | - | - | - |
| `openrouter:z-ai/glm-5.3` | GLM-5.3 | 1,048,576 | 943,718 | Reasoning, Tools |
| `openrouter:z-ai/glm-5.3-prime` | GLM 5.3 Prime | 1,000,000 | 131,072 | Reasoning, Tools |
| `openrouter:z-ai/glm-5.3-flash` | GLM-5.3-Flash | 1,048,576 | 943,717 | Reasoning, Vision, Tools |
| `openrouter:z-ai/glm-5.3-flashx` | GLM 5.3 FlashX | 1,048,576 | 131,072 | Reasoning, Vision, Tools |
| `openrouter:z-ai/glm-5v-turbo` | GLM-5V-Turbo | 202,752 | 131,072 | Reasoning, Vision, Tools |
| `openrouter:x-ai/grok-4.7` | Grok 4.7 | 500,000 | 450,000 | Reasoning, Vision, Tools |
| `openrouter:deepseek/deepseek-v4-pro` | DeepSeek V4 Pro | 1,048,576 | 384,000 | Reasoning, Tools |
| `openrouter:deepseek/deepseek-v4-flash` | DeepSeek V4 Flash | 1,048,576 | 943,717 | Reasoning, Tools |
| `openrouter:qwen/qwen3.8-max-0902` | Qwen3.8 Max 0902 | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `openrouter:google/gemini-3.8-flash` | Gemini 3.8 Flash | 1,048,576 | 65,536 | Reasoning, Vision, Tools |
| `openrouter:qwen/qwen3.7-plus` | Qwen3.7 Plus | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `openrouter:google/gemini-3.1-pro-preview` | Gemini 3.1 Pro Preview | 1,048,576 | 65,536 | Reasoning, Vision, Tools |
| `openrouter:minimax/minimax-m3` | MiniMax-M3 | 1,048,576 | 512,000 | Reasoning, Vision, Tools |
| `openrouter:moonshotai/kimi-k3` | Kimi K3 | 1,048,576 | 943,718 | Reasoning, Vision, Tools |
| `openrouter:google/gemini-3-flash-preview` | Gemini 3 Flash Preview | 1,048,576 | 65,536 | Reasoning, Vision, Tools |
### OpenCode Go
| Model ID | Name | Input Context | Output | Capabilities |
| - | - | - | - | - |
| `opencode-go:gpt-6-luna` | GPT-6 Luna | 922,000 | 128,000 | Reasoning, Vision, Tools |
| `opencode-go:glm-5.3` | GLM-5.3 | 1,000,000 | 131,072 | Reasoning, Tools |
| `opencode-go:glm-5.3-flash` | GLM-5.3-Flash | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:grok-4.7` | Grok 4.7 | 500,000 | 500,000 | Reasoning, Vision, Tools |
| `opencode-go:hy4-preview` | Hy4 preview | 1,024,000 | 64,000 | Reasoning, Tools |
| `opencode-go:deepseek-v4-pro` | DeepSeek V4 Pro (New) | 1,000,000 | 384,000 | Reasoning, Tools |
| `opencode-go:qwen3.8-max` | Qwen3.8 Max | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:qwen3.8-flash` | Qwen3.8 Flash | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:qwen3.7-plus` | Qwen3.7 Plus | 1,000,000 | 65,536 | Reasoning, Vision, Tools |
| `opencode-go:kimi-k3` | Kimi K3 | 1,048,576 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:minimax-m3` | MiniMax-M3 | 1,000,000 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:kimi-k2.7-code` | Kimi K2.7 Code | 262,144 | 262,144 | Reasoning, Vision, Tools |
| `opencode-go:mimo-v2.6-pro` | MiMo-V2.6-Pro | 1,048,576 | 131,072 | Reasoning, Vision, Tools |
| `opencode-go:mimo-v2.5` | MiMo V2.5 | 1,000,000 | 128,000 | Reasoning, Vision, Tools |
### Amazon Bedrock
Bedrock model IDs are passed through unchanged and are not validated against the static registry. Use any model ID supported by your AWS account and region.
| Model ID (example) | Notes |
| - | - |
| `bedrock:us.anthropic.claude-sonnet-4-5-20250929-v1:0` | Claude Sonnet 4.5 (US cross-region inference profile) |
| `bedrock:anthropic.claude-3-5-sonnet-20241022-v2:0` | Claude 3.5 Sonnet v2 |
| `bedrock:anthropic.claude-3-haiku-20240307-v1:0` | Claude 3 Haiku |
| `bedrock:meta.llama3-70b-instruct-v1:0` | Llama 3 70B Instruct |
| `bedrock:mistral.mistral-large-2402-v1:0` | Mistral Large |
| `bedrock:us.amazon.nova-pro-v1:0` | Amazon Nova Pro |
See the [Amazon Bedrock model catalog](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) for the full list. Model availability depends on the AWS region and on the [model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) granted in your account.
Authentication uses standard AWS environment variables (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_REGION`, optional `AWS_SESSION_TOKEN`) or `AWS_BEARER_TOKEN_BEDROCK`. See the [Model Configuration guide](/guides/model-configuration#amazon-bedrock) for details.
## Custom Providers
In addition to the built-in providers above, Dashboard Settings can connect
custom OpenAI Chat Completions, OpenAI Responses, or Anthropic Messages
endpoints. It discovers and saves available models and verifies the selected
protocol with a minimal completion. For OpenAI-compatible local endpoints, you
can also use the CLI:
```bash theme={"system"}
# Add Ollama
agentuse provider add ollama --url http://localhost:11434/v1
# Add LM Studio
agentuse provider add lmstudio --url http://localhost:1234/v1
```
Then use any model available on those endpoints:
```bash theme={"system"}
agentuse run agent.agentuse -m ollama:glm-5-flash:q4_K_M
agentuse run agent.agentuse -m ollama:qwen3.5:0.8b
agentuse run agent.agentuse -m lmstudio:qwen/qwen3.5-9b
```
See [Model Configuration](/guides/model-configuration#custom-providers) for full setup details.
## Usage
Specify a model in your agent file, pinned to a version or tracking the line:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5-5 # pinned
---
```
```yaml theme={"system"}
---
model: anthropic:claude-sonnet # newest in this line
---
```
Omit `model` entirely to use the configured default (`models.default` or
`AGENTUSE_MODEL`).
Or override via CLI, which accepts the same aliases:
```bash theme={"system"}
agentuse run agent.agentuse -m openai:gpt-5.6
agentuse run agent.agentuse -m openai:gpt
agentuse run agent.agentuse -m ollama:glm-5-flash:q4_K_M
```
# Session Storage
Source: https://docs.agentuse.io/reference/session-storage
Storage structure and data schemas for session logs
## Failure classification
Terminal execution errors retain their broad `code` and human-readable `message`.
New failures also carry an evidence-based `cause`, shared by the runtime, CLI
JSON output, API run responses, and plugin error events. Session-list responses
expose it as `errorCause`; full session records use `error.cause`.
| Cause | Meaning |
| - | - |
| `run_deadline` | The execution deadline fired. Broad code remains `TIMEOUT`. |
| `user_stopped`, `user_interrupt` | Explicit stop or CLI interruption. |
| `client_disconnect` | The attached client disconnected mid-run. Broad code is `CLIENT_DISCONNECT`. |
| `interrupted_unknown` | An abort without evidence of its source. Not a timeout. |
| `model_stall` | No model progress or model-step hard limit. `phase` and optional `attempts` provide detail. |
| `model_transport` | The model stream connection dropped. May include `attempts`. |
| `provider_rate_limit`, `provider_overloaded` | HTTP 429 or a structured provider overload response. |
| `provider_timeout`, `provider_server` | Provider request timeout or another provider server error, not the run deadline. |
| `provider_content_filter` | The provider's content filter truncated the response. Broad code is `CONTENT_FILTER`. |
| `provider_request`, `provider_permission` | Other provider request failure or HTTP 403. |
| `authentication`, `configuration` | Authentication or validated configuration failure. |
| `resume_state` | An approved run could not be resumed. The broad code is the specific resume failure. |
| `worker_interrupted`, `worker_protocol` | Worker loss or an unreadable worker response. |
| `request_deadline` | The daemon stopped waiting for a worker response. Does not prove the run stopped. |
| `unknown` | No more specific classification is supported by the evidence. |
Causes are additive. Consumers must tolerate missing or future values. Historical
errors are not rewritten or guessed from message text. `INCOMPLETE` remains an
agent-declared outcome, not a crash: its `cause` is the blocker kind
(`missing_tool`, `no_access`, `waiting_on_human`, and so on), with `error.subject`
naming the stuck thing and `error.causeSource` (`runtime`, `approval`, `agent`, or
`inferred`) saying how it was established. `agentuse sessions list --json` exposes
these as `errorCause` and `errorCauseSource`. Failure classification does not change retry
policy or imply that replaying a run with prior side effects is safe.
## Reviewer-rejected incomplete runs
A human rejection can leave a run `error/INCOMPLETE` while automatically setting
`dismissedAt`, which removes it from attention queues without erasing history.
An incomplete `report_outcome` accepts an optional `rejectionOnly` boolean: set it to `true`
when a human rejection in the run or a delegated child is the sole blocker. The
runtime verifies the recorded human decision and leaves the run visible if any
descendant is still active or has an independent failure. Machine review
rejections and manually dismissed failures do not establish human rejection.
When independent failures remain, set `rejectionOnly: false` and describe those
unresolved failures in `reason`, rather than repeating the rejected action.
Older declarations without the field retain same-session rejection handling;
propagating dismissal to a parent requires an explicit rejection-only declaration.
Existing historical sessions are not rewritten.
## Directory Structure
Sessions are stored under `AGENTUSE_DATA_DIR`, which defaults through XDG
conventions to `~/.local/share/agentuse`:
```
~/.local/share/agentuse/
└── project/
└── {git-hash}/ # Per-project isolation (or "global" for non-git)
└── session/
└── {sessionID}-{agentName}/
├── session.json
└── {messageID}/
├── message.json
└── part/
├── {partID}.json
└── ...
```
### Path Components
| Component | Description |
| - | - |
| `{git-hash}` | First 16 chars of SHA-256 hash of git root path |
| `{sessionID}` | ULID (time-sortable unique ID) |
| `{agentName}` | Sanitized agent name (lowercase, alphanumeric) |
| `{messageID}` | ULID for message exchange |
| `{partID}` | ULID for individual parts |
### Subagent Sessions
When an agent invokes subagents, their sessions are nested:
```
{sessionID}-{agentName}/
├── session.json
├── {messageID}/
└── subagent/
└── {subSessionID}-{subAgentName}/
├── session.json
├── {messageID}/
└── subagent/
└── {nestedSessionID}-{nestedAgentName}/
├── session.json
└── ...
```
Each descendant repeats the same structure beneath its direct parent. The
stored `parentSessionID` preserves that hierarchy for recursive delegation and
lets session views render important nested work in context.
## Data Schemas
### SessionInfo
Stored in `session.json` at the root of each session directory.
```typescript theme={"system"}
interface SessionInfo {
id: string; // ULID
parentSessionID?: string; // For subagent sessions
agent: {
name: string; // Agent name from YAML
filePath?: string; // Path to .agentuse file
description?: string; // Agent description
isSubAgent: boolean; // True if subagent execution
};
model: string; // e.g., "anthropic:claude-sonnet-5"
version: string; // AgentUse version
mock?: boolean; // True when the run executed in mock mode
config: {
timeout?: number; // Timeout in seconds
maxSteps?: number; // Max steps configured
mcpServers?: string[]; // MCP server names
subagents?: Array<{
path: string;
name?: string;
}>;
};
project: {
root: string; // Project root directory
cwd: string; // Working directory
};
time: {
created: number; // Unix timestamp (ms)
updated: number; // Unix timestamp (ms)
};
}
```
### Message
Stored in `{messageID}/message.json`. Contains both user input and assistant response.
```typescript theme={"system"}
interface Message {
id: string; // Message exchange ID
sessionID: string;
time: {
created: number; // When user sent message
completed?: number; // When assistant finished
};
user: {
prompt: {
task: string; // From .agentuse markdown body
user?: string; // From CLI args (optional)
};
};
assistant: {
system: string[]; // System prompts used
modelID: string;
providerID: string;
mode: string; // 'build', 'plan', etc.
path: {
cwd: string;
root: string;
};
cost: number;
tokens: {
input: number;
output: number;
reasoning: number;
cache: {
read: number;
write: number;
};
};
error?: {
message: string;
type?: string;
stack?: string;
};
};
}
```
### Parts
Stored in `{messageID}/part/{partID}.json`. Each part represents a discrete unit of content.
#### Base Fields
All parts include these fields:
```typescript theme={"system"}
interface PartBase {
id: string; // Part ID (ULID)
sessionID: string; // Session this part belongs to
messageID: string; // Message this part belongs to
}
```
#### Part Types
| Type | Description |
| - | - |
| `text` | Text output from the model |
| `reasoning` | Internal reasoning/thinking content |
| `tool` | Tool call with input, output, status, duration |
| `file` | File references |
| `agent` | Subagent invocations |
| `step-start` | Step boundary markers |
| `step-finish` | Step completion with token counts |
#### TextPart
```typescript theme={"system"}
interface TextPart extends PartBase {
type: 'text';
text: string;
synthetic?: boolean;
time?: {
start: number;
end?: number;
};
}
```
#### ReasoningPart
```typescript theme={"system"}
interface ReasoningPart extends PartBase {
type: 'reasoning';
text: string;
metadata?: Record;
time: {
start: number;
end?: number;
};
}
```
#### ToolPart
```typescript theme={"system"}
interface ToolPart extends PartBase {
type: 'tool';
callID: string; // Tool call ID from AI SDK
tool: string; // Tool name
state: ToolState;
}
type ToolState =
| { status: 'pending' }
| {
status: 'running';
input: unknown;
title?: string;
metadata?: Record;
time: { start: number };
}
| {
status: 'completed';
input: unknown;
output: unknown;
title?: string;
metadata?: Record;
time: { start: number; end: number };
}
| {
status: 'error';
input: unknown;
error: string;
metadata?: Record;
time: { start: number; end: number };
};
```
#### FilePart
```typescript theme={"system"}
interface FilePart extends PartBase {
type: 'file';
mime: string;
filename?: string;
url: string;
source?: {
type: 'file' | 'symbol';
path: string;
text?: {
value: string;
start: number;
end: number;
};
};
}
```
#### AgentPart
```typescript theme={"system"}
interface AgentPart extends PartBase {
type: 'agent';
name: string;
source?: {
value: string;
start: number;
end: number;
};
}
```
#### StepStartPart
```typescript theme={"system"}
interface StepStartPart extends PartBase {
type: 'step-start';
}
```
#### StepFinishPart
```typescript theme={"system"}
interface StepFinishPart extends PartBase {
type: 'step-finish';
cost: number;
tokens: {
input: number;
output: number;
reasoning: number;
cache: {
read: number;
write: number;
};
};
}
```
The `mock` flag is what keeps test runs out of the operational views. It is set
by `agentuse test` and `agentuse run --mock`, and absent on a normal run.
`agentuse sessions show` surfaces it as a warning line so a fabricated result is
never mistaken for a real one:
```
Mock: ⚠ mock run: some or all tool results were fabricated, not executed
```
List views mark the same sessions with a trailing `· mock`.
## Related
* [Testing Agents](/guides/testing-agents) - Validating an agent in mock mode
* [Session Logs Guide](/guides/session-logs) - How to use the sessions CLI
* [Environment Variables](/reference/environment-variables#storage) - Configure storage location
# Variables
Source: https://docs.agentuse.io/reference/variables
Variable placeholders available in AgentUse agent files
AgentUse supports variable placeholders in agent files (both YAML frontmatter and markdown content) to make your agent definitions more flexible and secure.
## Available Variables
| Variable | Syntax | Usage Locations | Description |
| - | - | - | - |
| Project Root | `${root}` | Filesystem paths, System prompt | Expands to the project root directory |
| Agent Directory | `${agentDir}` | Filesystem paths, System prompt | Expands to the directory containing the agent file |
| Temp Directory | `${tmpDir}` | Filesystem paths, System prompt | Expands to the system temp directory |
| Environment Variable | `${env:VAR_NAME}` | `mcpServers..auth.token` only | Expands to the value of an environment variable |
`${env:VAR_NAME}` is intentionally NOT supported in the system prompt (markdown content) to prevent accidental secret exposure to the LLM.
To show path-placeholder syntax literally in the model prompt instead of
resolving it, escape the dollar sign with a backslash: `\${root}` becomes the
literal text `${root}`. This is useful when an agent reviews or authors another
AgentUse file. The escape applies to `${root}`, `${agentDir}`, and `${tmpDir}`;
it does not enable environment-variable expansion.
## `${root}` - Project Root
The `${root}` variable expands to your project's root directory, which is detected by looking for markers like `.git`, `package.json`, or `.agentuse` directory.
### Usage
Use `${root}` in filesystem tool path configurations to reference paths relative to your project root, regardless of where you run the agent from.
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
tools:
filesystem:
- path: ${root}/src
permissions: [read, write]
- paths:
- ${root}/docs
- ${root}/tests
permissions: [read]
---
```
### Benefits
* **Portable**: Paths work regardless of current working directory
* **Consistent**: Always references the same location relative to project
* **Safe**: Restricts file access to defined project paths
## `${agentDir}` - Agent Directory
The `${agentDir}` variable expands to the directory containing the agent file. This is useful for referencing files bundled with your agent.
### Usage
Use `${agentDir}` to access files that are distributed alongside your agent file, such as scripts, configs, or data files.
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
tools:
filesystem:
- path: ${agentDir}/scripts
permissions: [read]
- path: ${agentDir}/data
permissions: [read, write]
---
```
### Benefits
* **Self-contained agents**: Bundle resources with your agent file
* **Relocatable**: Agent works regardless of where it's installed
* **No absolute paths**: Avoid hardcoding paths in agent definitions
`${agentDir}` is only available when the agent is loaded from a file. If the agent is loaded from a string or other source, this variable will not be resolved.
## `${tmpDir}` - Temp Directory
The `${tmpDir}` variable expands to the system's temporary directory (`os.tmpdir()`).
### Usage
Use `${tmpDir}` for temporary file storage that doesn't need to persist across agent runs.
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
tools:
filesystem:
- path: ${tmpDir}/agentuse
permissions: [read, write]
---
```
### Benefits
* **Platform-independent**: Works on macOS, Linux, and Windows
* **No cleanup needed**: Temp files are typically cleaned by the OS
* **Safe for scratch work**: Ideal for intermediate processing files
## `${env:VAR_NAME}` - Environment Variables
The `${env:VAR_NAME}` syntax allows you to reference environment variables in your configuration. This is particularly useful for sensitive values like API tokens.
### Usage
Currently supported in HTTP MCP server authentication:
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
mcpServers:
api_server:
url: https://api.example.com/mcp
auth:
type: bearer
token: ${env:API_TOKEN}
requiredEnvVars:
- API_TOKEN # Validates the variable exists before connecting
---
```
### How It Works
1. When the agent starts, `${env:API_TOKEN}` is replaced with `process.env.API_TOKEN`
2. If the environment variable is not set, a warning is logged
3. Use `requiredEnvVars` to ensure the variable exists before the agent runs
### Security Benefits
* **No hardcoded secrets**: Tokens stay in environment variables, not in code
* **Version control safe**: `.agentuse` files can be committed without exposing secrets
* **Explicit requirements**: `requiredEnvVars` documents what's needed to run the agent
## Variables in System Prompt
You can use path variables (`${root}`, `${agentDir}`, `${tmpDir}`) in the markdown content (system prompt) of your agent file. This helps the agent understand its environment.
### Usage
```markdown theme={"system"}
---
model: anthropic:claude-sonnet-5
tools:
filesystem:
- path: ${root}/data
permissions: [read, write]
---
You are a data processing agent.
## Your Environment
- Project root: ${root}
- Agent location: ${agentDir}
- Temp workspace: ${tmpDir}
You have read/write access to the project's data directory.
```
When the agent runs, these variables are resolved to actual paths, so the agent receives:
```
You are a data processing agent.
## Your Environment
- Project root: /home/user/my-project
- Agent location: /home/user/my-project/agents
- Temp workspace: /tmp
You have read/write access to the project's data directory.
```
### Security Note
`${env:VAR_NAME}` is **not supported** in the system prompt to prevent accidental secret exposure. Environment variables should only be used for authentication tokens in MCP server configuration, where they are handled securely and never sent to the LLM.
## Examples
### Complete Agent with All Path Variables
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: "Agent with multiple filesystem paths"
tools:
filesystem:
- path: ${root}/data
permissions: [read, write]
- path: ${agentDir}/templates
permissions: [read]
- path: ${tmpDir}/workspace
permissions: [read, write]
mcpServers:
external_api:
url: https://api.example.com/mcp
auth:
type: bearer
token: ${env:EXTERNAL_API_KEY}
requiredEnvVars:
- EXTERNAL_API_KEY
---
You are an agent with access to project files, bundled templates, and temp workspace.
```
### Self-Contained Agent with Bundled Resources
```yaml theme={"system"}
---
model: anthropic:claude-sonnet-5
description: "Agent with bundled scripts and data"
tools:
filesystem:
- path: ${agentDir}/scripts
permissions: [read]
- path: ${agentDir}/prompts
permissions: [read]
- path: ${tmpDir}/output
permissions: [read, write]
---
You have access to bundled scripts in ./scripts and prompt templates in ./prompts.
Write output files to the temp workspace.
```
### Multiple Environment Variables
```yaml theme={"system"}
mcpServers:
service_a:
url: https://a.example.com/mcp
auth:
type: bearer
token: ${env:SERVICE_A_TOKEN}
requiredEnvVars:
- SERVICE_A_TOKEN
service_b:
url: https://b.example.com/mcp
auth:
type: bearer
token: ${env:SERVICE_B_TOKEN}
requiredEnvVars:
- SERVICE_B_TOKEN
```
## Variable Resolution
Variables are resolved at different times:
| Variable | Resolution Time | Scope |
| - | - | - |
| `${root}` | Agent initialization | Filesystem paths, System prompt |
| `${agentDir}` | Agent initialization | Filesystem paths, System prompt |
| `${tmpDir}` | Agent initialization | Filesystem paths, System prompt |
| `${env:VAR_NAME}` | MCP connection setup | HTTP auth tokens only |
## Troubleshooting
Ensure you're using the correct syntax:
* Project root: `${root}` (lowercase)
* Agent directory: `${agentDir}` (camelCase)
* Temp directory: `${tmpDir}` (camelCase)
* Environment variables: `${env:VAR_NAME}` (with `env:` prefix)
The old `${VAR_NAME}` syntax without the `env:` prefix is not supported.
`${agentDir}` is only available when the agent is loaded from a file path. It will not resolve when:
* The agent is loaded from a URL
* The agent is loaded from a string
* The agent file path is not passed to the runner
In these cases, `${agentDir}` will remain as literal text and path validation may fail.
If you see a warning about an environment variable not being set:
1. Check that the variable is exported in your shell or defined in `.env`
2. Verify the variable name matches exactly (case-sensitive)
3. Add the variable to `requiredEnvVars` for early validation
If `${root}` isn't pointing to the expected directory:
1. Ensure your project has a recognizable marker (`.git`, `package.json`, etc.)
2. Run the agent from within your project directory
3. Use `agentuse run -C /path/to/project` to specify the project root
## Next Steps
Complete YAML configuration reference
All environment variables used by AgentUse