Files
fusion/docs/agents.md
gsxdsm 1c4a3f4e4d feat(FN-1452): make structured run records the source of truth for agent run state
- Update AGENTS.md with authoritative run lifecycle semantics documentation
- Add API-level regression test for repeated manual run prevention
- Update run lifecycle tests to match corrected behavior
- Refactor AgentStore to use structured run records as the authoritative source for run state
- Improve run status queries with better filtering and ordering
2026-04-09 18:37:48 -07:00

225 lines
6.9 KiB
Markdown

# Agents
[← Docs index](./README.md)
Fusion uses multiple agent roles for triage, execution, review, and merge workflows.
## Agents View (Dashboard)
The agents surface provides:
- Agent list and status
- Detail/config panels
- Runtime metrics
- Run history
- Task assignment context
![Agents view](./screenshots/agents-view.png)
## Built-In Agent Prompt Templates
Fusion includes built-in templates for role prompts:
- `default-executor`
- `default-triage`
- `default-reviewer`
- `default-merger`
- `senior-engineer`
- `strict-reviewer`
- `concise-triage`
These can be assigned per role using `agentPrompts.roleAssignments`.
## Per-Agent Configuration
Agents can be configured with:
- Custom instructions
- Heartbeat interval/timeout limits
- Max concurrent heartbeat runs
Heartbeat values are validated and minimum-clamped.
## New Agent Presets (Dashboard UI)
The New Agent dialog in the dashboard provides quick-start presets for common agent roles. Each preset includes:
- **Name and icon** - Display identification
- **Professional title** - Descriptive role title
- **Soul** - Personality and operating principles defining how the agent thinks and communicates
- **Instructions** - Actionable behavioral guidelines
### Preset Library Location
Preset definitions live in `packages/dashboard/app/components/agent-presets/`:
```
agent-presets/
├── index.ts # Exports AGENT_PRESETS and helper functions
├── ceo/soul.md # Chief Executive Officer soul
├── cto/soul.md # Chief Technology Officer soul
├── cmo/soul.md # Chief Marketing Officer soul
├── cfo/soul.md # Chief Financial Officer soul
├── engineer/soul.md # Software Engineer soul
├── backend-engineer/soul.md
├── frontend-engineer/soul.md
├── fullstack-engineer/soul.md
├── qa-engineer/soul.md
├── devops-engineer/soul.md
├── ci-engineer/soul.md
├── security-engineer/soul.md
├── data-engineer/soul.md
├── ml-engineer/soul.md
├── product-manager/soul.md
├── designer/soul.md
├── marketing-manager/soul.md
├── technical-writer/soul.md
├── triage/soul.md
└── reviewer/soul.md
```
### Soul File Format
Each `soul.md` file is a Markdown document containing:
```markdown
# Soul: [Role Name]
[First-person identity statement]
## Operating Principles
[Bullet points describing key behaviors]
## Communication Style
[How the agent communicates]
```
Soul content should be:
- **First-person** - Written from the agent's perspective ("I am...")
- **Role-specific** - Defines the unique character of this role
- **Actionable** - Describes concrete behaviors, not abstract qualities
- **Paperclip-inspired** - Clear ownership, decision discipline, communication standards
### Adding or Modifying Presets
1. Create or edit the `soul.md` file in the appropriate directory
2. Update `index.ts` if adding a new preset (export the imported soul and add to `AGENT_PRESETS` array)
3. Run tests to verify: `pnpm --filter @fusion/dashboard exec vitest run app/components/__tests__/agent-presets.test.ts`
### Preset vs Engine Templates
**Dashboard presets** are a UI-only concept that populates the New Agent dialog fields (name, icon, role, soul, instructionsText). They don't map to engine types.
**Engine role prompts** (in `agentPrompts` settings) define the actual agent behavior when executing tasks. These are separate from dashboard presets and live in project settings.
This separation means:
- Presets provide starting point personality and instructions for new agents
- Engine templates control actual task execution behavior
- An agent created from a preset can have its engine role prompt customized independently
## Configurable Agent Prompts (`agentPrompts`)
`agentPrompts` project setting supports:
- `templates[]`: custom prompt templates by role
- `roleAssignments`: map role → template ID
When no assignment is configured, Fusion falls back to built-in defaults.
## Inter-Agent Messaging
Messaging is available in dashboard mailbox UI and CLI.
```bash
fn message inbox
fn message outbox
fn message send AGENT-001 "Please prioritize FN-420"
fn message read MSG-123
fn message delete MSG-123
fn agent mailbox AGENT-001
```
## Agent Spawning
Executor sessions can spawn child agents through `spawn_agent`.
Behavior:
- Child agents run in separate worktrees
- Parent/child relationship is tracked
- Limits enforced:
- `maxSpawnedAgentsPerParent` (default 5)
- `maxSpawnedAgentsGlobal` (default 20)
- Child sessions terminate when parent task ends
## Heartbeat Monitoring and Trigger Scheduling
Fusion's `HeartbeatTriggerScheduler` supports three trigger types:
- `timer` — periodic wake based on heartbeat interval
- `assignment` — wake when task is assigned to agent
- `on_demand` — manual run trigger (`POST /api/agents/:id/runs`)
All triggers respect per-agent `maxConcurrentRuns` and produce structured wake context metadata.
## Heartbeat Run Lifecycle
Agent runs have a defined lifecycle managed by `AgentStore`:
### Run States
A heartbeat run can be in one of these states:
- `active` — Run is currently executing
- `completed` — Run finished successfully (via `endHeartbeatRun(runId, "completed")`)
- `terminated` — Run was stopped (via `endHeartbeatRun(runId, "terminated")`)
- `failed` — Run encountered an error
### Run Lifecycle API
- `startHeartbeatRun(agentId)` — Creates a new run and persists it to structured storage
- `endHeartbeatRun(runId, status)` — Ends a run with terminal status, updates persisted state
- `getActiveHeartbeatRun(agentId)` — Returns the current active run (or null)
- `getCompletedHeartbeatRuns(agentId)` — Returns all terminal runs (newest first)
- `saveRun(run)` — Persists run to structured storage
- `getRunDetail(agentId, runId)` — Gets a specific run by ID
### Active-Run Conflict Semantics
When an agent already has an active run, attempts to start a new run return **409 Conflict**:
```
POST /api/agents/:id/runs → 409 { error: "Agent already has an active run", details: { runId } }
```
After a run is completed (or terminated), a new run can be started successfully:
```
POST /api/agents/:id/runs → 201 { id: "run-xxx", status: "active", ... }
```
### Storage Architecture
Run records are stored in structured JSON files at `.fusion/agents/{agentId}-runs/{runId}.json`.
Heartbeat events are also appended to `.fusion/agents/{agentId}-heartbeats.jsonl` for legacy compatibility. The structured storage is the source of truth; heartbeat events provide a fallback for older run data.
### Stopping Runs
Use `POST /api/agents/:id/runs/stop` to terminate an active run:
```
POST /api/agents/:id/runs/stop → 200 { ok: true, runId: "run-xxx" }
```
If there's no active run, returns `{ ok: true, message: "No active run" }`.
## Related Docs
- [Workflow Steps](./workflow-steps.md)
- [Settings Reference](./settings-reference.md)
- [Architecture](./architecture.md)