rolebox
OpenCode plugin — define custom AI agent roles via YAML with per-role prompts, models, skills, and permissions
Package details
Install rolebox from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:rolebox- Package
rolebox- Version
1.1.0- Published
- Jul 31, 2026
- Downloads
- 2,932/mo · 389/wk
- Author
- ericmoin
- License
- MIT
- Types
- extension
- Size
- 5.6 MB
- Dependencies
- 10 dependencies · 9 peers
Pi manifest JSON
{
"extensions": [
"./dist/pi-extension.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
rolebox
Upgrading from 0.x.x? rolebox 1.x replaced the 0.x execution model. In 0.x, workflows were declared in
role.yaml(collaboration:block with built-in topologies likepipeline,review-loop,star) and routed automatically by the v1 graph machinery. In 1.x, workflows are imperatively built and run on a graph execution engine — you callgraph_create→graph_add_node/graph_add_edge→graph_runand observe results withgraph_status. The v1 collaboration auto-advance machinery was decommissioned (the legacy task-query surface survives as a thintask_*compatibility layer). See Graph execution engine and docs/graph-legacy-v1-decommission.md.
Quick Start
cd ~/.config/opencode && npm install rolebox
Add to opencode.jsonc:
{
"plugin": ["rolebox"]
}
Create your first role:
rolebox init my-agent -y
A ready-to-use role directory is created in ~/.config/opencode/rolebox/my-agent/. Restart opencode and pick the agent from your agent list.
To install the Emperor orchestrator:
rolebox install emperor
Why rolebox
- Persistent memory — SQLite + FTS5 stores decisions, conventions, and lessons across sessions. Workspace-scoped or role-private. Relevant memories auto-inject at session start via
<available_memory>. - Multi-agent dispatch — define specialist roles in YAML and dispatch them in parallel with concurrency control and budget tracking. The Emperor orchestrator handles planning, delegation, validation, and revision across a team of sub-agents — without writing code.
- LSP integration and hashline editing — 30+ language server tools (go-to-definition, diagnostics, references, rename, completions) available inside your assistant. Content-hash-anchored editing replaces fragile line numbers so edits survive concurrent file changes.
Graph execution engine
Introduced in 1.0, the graph execution engine is how rolebox now runs multi-agent workflows. Instead of a single orchestrator deciding who to dispatch to and when, you build an explicit graph of nodes and edges and the engine executes it: nodes are dispatched to sub-agents, edges carry results and signals between them, and the engine tracks budget, approval gates, and loop caps on every dispatch.
The engine is driven by an imperative toolset — graph_create, graph_add_node, graph_add_edge, graph_add_loop, graph_run, graph_status, graph_cancel, graph_approve — registered in src/graph/tools/index.ts. The underlying engine lives in src/graph/engine/* (see docs/graph-engine-architecture.md).
Concepts
- Nodes — role-agnostic
{agent, prompt}tuples.graph_add_noderegisters one worker node; structural validation is atomic (an invalid node is rejected without mutating the graph). - Edges — directed edges define data flow and signal routing. Edge
typeis one of:always— activate the target when the source completes,on_signal— activate on a specific signal type (requiressignal_filter, e.g.["revise_needed"]),on_condition— activate when a named condition evaluates true (requirescondition).
- Loop groups —
graph_add_loopdeclares a bounded cycle of nodes with a hardmax_traversalscap and optional soft termination conditions (converged,stuck,result_matches,timeout_ms,signal, …). Loops re-dispatch within the same engine state (mode: "inherit"); per-round session isolation is not supported — use a separate graph per round. - Approval gates — a node with
needs_approval: truepauses the graph at that node. The engine emits[GRAPH BLOCKED]; the human resolves it withgraph_approve(graph_id, node_id, action)whereactionisapprove(continue) orreject(re-enter the node with feedback when it belongs to a loop group, otherwise escalate). - Observability —
graph_statusqueries node, loop, or graph state:format=treerenders the node dependency tree,scope=persistedreads graphs hydrated from the on-disk engine-state store,include_outputreturns materialized node results, andinclude_history/streamsurface loop rounds and signal events. Persisted state lives in.rolebox/state/engine-*.jsonplus an append-onlygraph-events-*.ndjsonevent log.
Usage
graph_run is non-blocking — it dispatches ready root nodes and returns immediately with phase, active_nodes, and pending_nodes. End your turn after graph_run; the engine emits a [GRAPH COMPLETE] system-reminder when all nodes finish (or [GRAPH BLOCKED] when a node awaits approval). On the next turn, read results once via graph_status(graph_id, include_output=true).
1. graph_create(name="review-workflow") → { graph_id: "review-workflow", ... }
2. graph_add_node(graph_id="review-workflow", id="writer",
agent="emperor--jinyiwei--ui", prompt="Build the component")
3. graph_add_node(graph_id="review-workflow", id="reviewer",
agent="emperor--jinyiwei--test", prompt="Review the result")
4. graph_add_edge(graph_id="review-workflow",
from="writer", to="reviewer", type="always")
5. graph_run(graph_id="review-workflow") → non-blocking; end your turn
6. [GRAPH COMPLETE] system-reminder arrives
7. graph_status(graph_id="review-workflow", include_output=true) → read results once
Loop groups and approval gates compose on top of the same node/edge model:
graph_add_loop(graph_id="review-workflow", id="revise", nodes=["writer", "reviewer"],
max_traversals=3, termination={ any_of: [{ signal: "revise_needed" }] })
graph_add_node(graph_id="review-workflow", id="finalize",
agent="emperor--jinyiwei--docs", prompt="Finalize", needs_approval=true)
graph_approve(graph_id="review-workflow", node_id="finalize", action="approve")
See docs/graph-engine-architecture.md for the full engine architecture map and docs/graph-legacy-v1-decommission.md for how the v1 subsystem was replaced.
Loop mode
Run the same task across fresh sessions and iterate automatically — useful for refinement passes, batch fixes, and self-correcting workflows.
Features at a glance
- Dispatch system — parallel background execution with concurrency control, budget tracking, task retry, and dependency graphs. See docs/dispatch-config.md.
- Graph execution engine — explicit node/edge workflows with non-blocking
graph_run, signal- and condition-based edges, bounded loop groups, and approval gates. See docs/graph-engine-architecture.md. - Desktop notifications — native OS notifications with idle detection, quiet hours, event filtering, and smart throttling. See docs/hooks.md.
- Session management — 10 tools for searching, exporting, forking, diffing, and inspecting session history. See docs/session-tools-strategy.md.
- Function state machine — functions have active, gated, and dormant phases with evidence observation and artifact tracking. See docs/functions.md.
- Context assembly — cross-domain search across memory, assets, tasks, and sessions with token-bounded result blocks.
- Asset management — hot-reload roles, skills, and references at runtime; asset search, inspection, validation, and composition analysis.
Comparison: opencode vs + rolebox
| Capability | Raw opencode | + rolebox |
|---|---|---|
| Persistent memory | ❌ Sessions start blank | ✅ SQLite + FTS5, auto-inject past decisions |
| Multi-agent teams | ❌ Single agent | ✅ YAML-defined specialists, parallel dispatch |
| LSP integration | ❌ No language server access | ✅ 30+ tools (go-to-def, references, rename, diagnostics…) |
| Hashline editing | ❌ Line-number based | ✅ Content-hash anchored — edits never drift |
| Background dispatch | ❌ Sequential | ✅ Real concurrency with budget tracking |
| Hot-reload assets | ❌ Restart required | ✅ Edit YAML, reload instantly |
CLI Reference
| Command | Description |
|---|---|
rolebox init <name> |
Scaffold a new role directory |
rolebox install <name> |
Install a role from the registry |
rolebox status |
List all installed roles and their status |
rolebox info <name> |
Detailed role inspection |
rolebox sync |
Sync installed roles with registry |
rolebox monitor |
Live dispatch metrics dashboard (TUI) |
rolebox memory search <query> |
Full-text search across persistent memory |
rolebox --version |
Show version |
Role Gallery
Pre-built roles available from the oh-my-role registry:
| Role | What it does |
|---|---|
| emperor | Top-level orchestrator — plans, delegates, validates complex work across a specialist team |
| software-architect | System design, trade-off analysis, ADRs, C4 models, and architecture reviews |
| react-frontend | React/Next.js component design, state management, and frontend architecture |
| ai-designer | AI application design with humane UX gates, interaction modeling, and design system creation |
| tauri | Desktop app development with Tauri v2 — IPC, plugins, window management, system tray |
| dart-flutter | Cross-platform mobile and desktop Flutter development with full gate review pipeline |
Install any role with rolebox install <name> and restart opencode.
Model Alias Configuration
Roles published on the oh-my-role registry often use placeholder model names (e.g. PLACEHOLDER, YOUR_MODEL_HERE) instead of real provider/model identifiers. Rather than editing each role's role.yaml manually, you can define local alias mappings once.
Create or edit ~/.config/opencode/role_config.yaml (same directory as your opencode.jsonc):
model_aliases:
PLACEHOLDER: hfai/deepseek-v4-pro-max
YOUR_MODEL_HERE: anthropic/claude-opus-4
# key = placeholder string from role.yaml
# value = provider/model_id for your actual model
How resolution works
At role load time, each model: field goes through a non-destructive fallback chain:
- Known models first — if the value matches a model already configured in your
opencode.jsoncprovider list, it passes through unchanged. - Alias lookup — if not known, rolebox checks
model_aliasesinrole_config.yaml. When a match is found, the mapped value is used (single-hop — no recursive chaining). - Passthrough with warning — if neither matches, the original value is preserved and a warning is logged. Loading never fails because of an unrecognized model.
This resolution covers both the role-level model field and all subagent model fields, including inherited values.
Error handling
- Missing config file — treated as an empty alias map; no error.
- Malformed YAML — warns and falls back to empty aliases; loading continues.
- Invalid alias entries (empty keys, non-string values, empty values) — skipped with a warning; valid entries in the same file still apply.
Hot-reload
Edits to role_config.yaml take effect on the next hot-reload cycle or role bootstrap. No process restart is required for the primary runtime. For CLI tools that bypass the bootstrap path, a restart is needed.
Docs Index
| Topic | Docs |
|---|---|
| Create a Role | docs/create-a-role.md |
| role.yaml Reference | docs/role-yaml.md |
| Directory Structure | docs/directory-structure.md |
| Functions | docs/functions.md |
| Skills | docs/skills.md |
| References | docs/references.md |
| Subagents | docs/subagents.md |
| Collaboration Graph | docs/collaboration-graph.md |
| Graph Engine Architecture | docs/graph-engine-architecture.md |
| Graph v1 Decommission | docs/graph-legacy-v1-decommission.md |
| Memory Strategy | docs/memory-strategy.md |
| CLI | docs/cli.md |
| Session Tools | docs/session-tools-strategy.md |
| Dispatch Config | docs/dispatch-config.md |
| Custom Hooks | docs/hooks.md |
| Extensions | docs/extensions.md |
| Registry | docs/registry.md |
| Error Handling | docs/error-handling.md |
| Limitations | docs/limitations.md |
| Compatibility | docs/compatibility.md |
Contributing
Contributions welcome. See CONTRIBUTING.md for guidelines.
License
MIT — see the LICENSE file.