Agent Contributor Onboarding¶
This guide helps you understand the agent ecosystem and contribute to it. By the end you'll know how to deploy the existing agent stack, create new agents and workflows, navigate the label-driven pipeline, and use git-spice for stacked branch management.
Prerequisites¶
- Services running locally (see Getting Started)
ghCLI authenticated:gh auth login- git-spice installed:
brew install abhinav/tap/git-spice - git-spice initialized in your clone (one-time, human step - see git-spice setup)
1. Quick start - deploy the agent stack¶
The project ships a complete agent stack in .agentd/. One command creates every room,
agent, and workflow in the correct order:
Apply order: rooms → agents → workflows. Rooms must exist before agents join them; agents must be running before workflows reference them by name.
Preview what would be created without making changes:
Tear everything down in reverse order:
What gets created¶
.agentd/
├── rooms/
│ ├── engineering.yml # General coordination channel
│ ├── announcements.yml # Broadcast announcements
│ ├── operations.yml # Pipeline status digests (conductor)
│ └── security.yml # Audit findings (security agent)
├── agents/
│ ├── conductor.yml # Pipeline orchestrator
│ ├── planner.yml # Issue breakdown and planning
│ ├── worker.yml # Issue implementation
│ ├── reviewer.yml # PR code review
│ ├── enricher.yml # Issue enrichment
│ ├── tester.yml # Test coverage
│ ├── security.yml # Security auditing
│ └── architect.yml # Architecture review
└── workflows/
├── issue-worker.yml # Dispatches on agent label
├── plan-worker.yml # Dispatches on plan-agent label
├── pull-request-reviewer.yml
├── docs-worker.yml
├── research-worker.yml
├── enrichment-worker.yml
├── test-worker.yml
└── security-worker.yml
Idempotent
If a room or agent with the same name already exists, agent apply reuses it rather
than creating a duplicate. Re-running agent apply .agentd/ is safe.
2. Creating a new agent¶
Agent definitions live in .agentd/agents/<name>.yml.
Human approval required
Changes to .agentd/agents/*.yml are gated - they alter agent behavior for all future
runs. A human must review and merge these changes. Do not modify existing agent YAML
files autonomously.
Minimal agent¶
name: my-agent
working_dir: "."
system_prompt: |
You are a specialist agent for the agentd project.
Describe your role and responsibilities here.
Full field reference¶
# Required
name: my-agent # Unique agent name
# Optional - sensible defaults shown
working_dir: "." # Resolved relative to YAML file at apply time
shell: /bin/zsh # Shell for the tmux session
worktree: false # Isolated git worktree per task
model: claude-sonnet-4-6 # Claude model (omit to use default)
# Optional - directories outside working_dir the agent can access
additional_dirs:
- ../other-repo # Relative to YAML file
- /opt/shared/configs # Absolute path
# Optional - initial prompt sent once after the agent connects
prompt: "Read CLAUDE.md and summarize this project."
# Optional - system prompt for the Claude session
system_prompt: |
You are a ...
# Optional - tool restrictions (default: allow_all)
tool_policy:
mode: deny_list
tools:
- "Write(crates/**)" # Block writes to production source
- "Edit(.agentd/**)" # Block modification of agent configs
# Optional - rooms the agent auto-joins at startup
rooms:
- engineering # Plain name = member role
- name: announcements
role: observer # Read-only
- name: operations
role: admin # Can manage participants
System prompt best practices¶
The system prompt defines what the agent is and how it behaves. Look at the existing agents
in .agentd/agents/ for patterns. Key things to include:
- Role statement - one sentence describing what the agent does and for which project
- Process section - numbered steps the agent follows for each task
- Scope constraints - what the agent must NOT do (as important as what it should do)
- Branch/PR workflow - how to use git-spice (copy the pattern from
worker.yml) - Memory Protocol - how the agent reads and writes shared memory (see below)
Memory Protocol¶
Every agent in the project follows the same memory pattern. Include this block in the
system prompt, substituting your agent's identity for <name>:
## Memory Protocol
You have access to a shared memory service via the `agent memory` CLI.
Your agent identity for memory operations is "<name>".
### On Startup
Before beginning any task, retrieve relevant context:
1. Search for prior decisions in your area:
agent memory search "<topic>" --as-actor <name> --limit 5 --json
2. Search for memories tagged with your role:
agent memory search "<name> guidance" --as-actor <name> --tags <name> --limit 5 --json
3. Review results and incorporate relevant context.
### After Completing Work
Store significant findings, decisions, or gotchas:
agent memory remember "<what you learned>" \
--created-by <name> --type information \
--tags <name>,<topic> --visibility public
### What to Remember
- Decisions and their rationale
- Patterns that worked or failed
- Gotchas not captured in code or docs
### What NOT to Remember
- Information already in code, comments, or git history
- Ephemeral task state
Tool policies¶
Use tool policies to limit what an agent can do. The tester and security agents show two common patterns:
See Tool Policies for the full reference.
3. Creating a new workflow¶
Workflows connect an agent to a task source. They live in .agentd/workflows/<name>.yml.
Minimal workflow¶
name: my-workflow
agent: my-agent # Agent name (resolved to UUID at apply time)
source:
type: github_issues
owner: geoffjay
repo: agentd
labels:
- my-label # Issues with this label are dispatched
state: open
poll_interval: 60 # Seconds between polls
enabled: true
prompt_template: |
You have been assigned a task.
Issue #{{source_id}}: {{title}}
URL: {{url}}
Labels: {{labels}}
Description:
{{body}}
Supported trigger types¶
Prompt template variables¶
All {{variable}} placeholders available in GitHub issue/PR workflows:
| Variable | Description | Example |
|---|---|---|
{{source_id}} |
Issue or PR number | 42 |
{{title}} |
Issue/PR title | "Fix login bug" |
{{body}} |
Full issue/PR body (markdown) | "## Overview\n..." |
{{url}} |
GitHub URL | "https://github.com/org/repo/issues/42" |
{{labels}} |
Comma-separated labels | "bug, agent" |
{{assignee}} |
Assigned user (empty if none) | "alice" |
For cron workflows: {{fire_time}}, {{cron_expression}}. For delay: {{run_at}}.
Validate a template before deploying:
Writing effective prompt templates¶
The prompt template is the entire instruction set the agent receives per task. It should:
- Repeat key context - include issue number, URL, and body so the agent doesn't need to re-fetch them
- Include a memory step - have the agent search memory before starting work (see the
issue-worker.ymlpattern) - Give explicit instructions - numbered steps, not vague guidance
- Specify the branch naming - tell the agent exactly how to create the branch
- Specify the completion step - how to remove the dispatch label when done
Look at .agentd/workflows/issue-worker.yml and .agentd/workflows/research-worker.yml
for complete, production-tested examples.
4. Label conventions¶
The pipeline is driven entirely by GitHub labels. Understanding which labels do what is essential before contributing.
Pipeline state labels (blue)¶
These encode the current state of an issue or PR. The conductor agent reads and sets them.
| Label | Set by | Meaning |
|---|---|---|
needs-triage |
Human / automation | New issue awaiting triage |
triaged |
Planner agent | Issue scoped and ready |
merge-ready |
Reviewer agent | PR approved + CI green |
merge-queue |
Conductor | Actively queued for merge |
Status / warning labels (amber + red)¶
| Label | Set by | Meaning |
|---|---|---|
needs-rework |
Reviewer | PR has change requests |
needs-restack |
Reviewer / conductor | Branch is behind parent; run git-spice upstack restack |
needs-refinement |
Human / planner | Issue lacks enough detail |
needs-tests |
Reviewer / tester | Missing test coverage |
Agent dispatch labels (green + specialist)¶
Applying one of these labels triggers the matching workflow to pick up the issue and dispatch it to the corresponding agent. The agent removes the label when it finishes.
| Label | Workflow | Agent dispatched | Target |
|---|---|---|---|
agent |
issue-worker |
worker | Issue |
docs-agent |
docs-worker |
documenter | Issue |
plan-agent |
plan-worker |
planner | Issue |
enrich-agent |
enrichment-worker |
enricher | Issue |
test-agent |
test-worker |
tester | Issue |
refactor-agent |
refactor-worker |
refactor agent | Issue |
research-agent |
research-worker |
research agent | Issue |
security-agent |
security-worker |
security agent | Issue |
review-agent |
pull-request-reviewer |
reviewer | Pull request |
conductor-sync |
conductor sync | conductor | Manual trigger |
Re-triggering an agent
Dispatch is deduplicated - re-applying a label to an already-dispatched issue has no effect. To re-trigger, remove the label first, then re-add it. This creates a new event that the scheduler treats as a fresh task.
Adding a new dispatch label¶
When adding a new agent to the pipeline, you need:
- A new entry in
.github/labels.yml - A new agent in
.agentd/agents/<name>.yml - A new workflow in
.agentd/workflows/<name>-worker.ymlreferencing that label - An entry in the dispatch table in
docs/public/pipeline-state-machine.md
5. git-spice for agents¶
All branch management in this project uses git-spice. Raw git checkout -b and
gh pr create are not used - use the git-spice equivalents.
One-time setup¶
# Install (macOS)
brew install abhinav/tap/git-spice
# Initialize in your clone (sets trunk = main)
git-spice repo init --trunk main
Human-only: git-spice auth login
The OAuth login flow is interactive and cannot be scripted. A human must run this
once per clone before any git-spice branch submit operations:
Restore project config defaults if they are missing after a fresh clone:
git config spice.submit.navigationComment true
git config spice.submit.navigationComment.downstack true
git config spice.log.all true
git config spice.log.crStatus true
Session start¶
Always sync at the start of every working session to pick up merged PRs and rebase any dependent branches:
Core workflow¶
# 1. Start from the milestone base branch
git checkout feature/autonomous-pipeline
# 2. Create a stacked branch
git-spice branch create issue-NNN -m "feat: brief description"
# Naming conventions:
# Implementation: issue-NNN
# Documentation: docs/issue-NNN
# Tests: test/issue-NNN
# Refactoring: refactor/issue-NNN
# 3. Make changes, then commit
git-spice commit create -m "feat(scope): description (closes #NNN)"
# 4. Submit as a PR - idempotent (creates or updates)
git-spice branch submit --fill --no-prompt --label review-agent
Handling dependencies (stacking)¶
When issue B depends on issue A being merged first, stack B's branch on top of A's:
# Check out A's branch, then create B on top of it
git checkout issue-A
git-spice branch create issue-B -m "feat: description"
The issue body should declare this with a ## Blocked By section:
## Blocked By
- #A - description of why B needs A first
## Stack Base
Branch off `feature/autonomous-pipeline`. PR back into it.
Addressing review feedback¶
When a PR receives needs-rework:
# Make fixes, then amend the commit
git-spice commit amend -m "feat(scope): description (address review feedback)"
# Resubmit - updates the existing PR
git-spice branch submit --fill --no-prompt --label review-agent
Merge conflict / needs-restack¶
When a PR receives needs-restack, the branch has fallen behind its parent:
git-spice repo sync # Sync parent branches first
git-spice upstack restack # Rebase this branch on its parent
git-spice branch submit --fill --no-prompt --label review-agent
Useful inspection commands¶
# See the full branch stack and PR status
git-spice log short
# Detailed stack with parent/child relationships
git-spice log long
# Check spice data is intact
git log --oneline refs/spice/data | head -5
Non-interactive flags¶
Agents must never use interactive git-spice commands. Always pass these flags:
| Command | Non-interactive form |
|---|---|
git-spice branch submit |
git-spice branch submit --fill --no-prompt |
git-spice stack submit |
git-spice stack submit --fill --no-prompt |
--fill populates the PR title/body from commit messages. --no-prompt suppresses
all interactive confirmation prompts.
6. Room configuration¶
Rooms are communication channels that agents and humans share. They are defined in
.agentd/rooms/<name>.yml and created as part of agent apply .agentd/.
Room template¶
name: engineering
topic: "Engineering team coordination"
description: "General channel for engineering agents and humans."
type: group # direct | group | broadcast
participants:
- identifier: conductor
kind: agent
role: member
- identifier: geoff
kind: human
role: admin
display_name: "Geoff"
Room types¶
| Type | Who can post | Use case |
|---|---|---|
group |
All members | Agent/human coordination |
direct |
Both participants | One-to-one |
broadcast |
Admins only | Announcements, status feeds |
Participant roles¶
| Role | Post messages | Manage participants |
|---|---|---|
member |
Yes | No |
admin |
Yes | Yes |
observer |
No | No |
Existing rooms¶
| Room | Type | Purpose |
|---|---|---|
engineering |
group | General agent/human coordination |
announcements |
group | Project-wide announcements |
operations |
group | Pipeline status (conductor posts digests here) |
security |
group | Audit findings from the security agent |
Adding an agent to a room¶
In the agent YAML (preferred - the agent joins automatically at startup):
# .agentd/agents/my-agent.yml
rooms:
- engineering # member role
- name: announcements
role: observer
Via CLI (for a running agent, without redeploying):
agent communicate add-participant \
--room engineering \
--identifier my-agent \
--kind agent \
--role member
Adding a room to the project requires:
- A new file
.agentd/rooms/<name>.yml - Adding each agent that should join to their
rooms:list - Running
agent apply .agentd/rooms/<name>.yml(oragent apply .agentd/)
Idempotent creation
If a room already exists, agent apply skips creation - it does not update the
topic, description, or participants. To modify an existing room, use the CLI directly.
7. Testing agents before deploying¶
Validate templates without creating anything¶
agent apply --dry-run .agentd/
agent apply --dry-run .agentd/agents/my-agent.yml
agent apply --dry-run .agentd/workflows/my-workflow.yml
Validate prompt templates¶
agent orchestrator validate-template "Fix #{{source_id}}: {{title}}\n{{body}}"
agent orchestrator validate-template --file .agentd/workflows/my-workflow.yml
Deploy a single agent for testing¶
# Create just the agent (not its workflow)
agent apply .agentd/agents/my-agent.yml
# Check it started
agent orchestrator list-agents --status running
Send a one-off task¶
# Find the agent ID
AGENT_ID=$(agent orchestrator list-agents --json | jq -r '.[] | select(.name=="my-agent") | .id')
# Send a test prompt directly (bypasses the workflow)
agent orchestrator send-message "$AGENT_ID" "This is a test task. Describe what you would do for issue #1."
Watch the agent work in real time¶
# Stream structured output (tool calls, text, permission requests)
agent orchestrator stream "$AGENT_ID"
# Attach to the raw tmux session for full terminal view
agent orchestrator attach --name my-agent
# Detach without killing: Ctrl-b d
Approve tool requests interactively¶
For agents with require_approval policy, approve tool calls as they come in:
# In one terminal - watch for permission requests
agent orchestrator stream "$AGENT_ID"
# In another - approve or deny
agent orchestrator list-approvals
agent orchestrator approve <APPROVAL_ID>
agent orchestrator deny <APPROVAL_ID>
Test a workflow dispatch manually¶
Trigger a manual-type workflow without waiting for a label event:
# Find the workflow ID
WORKFLOW_ID=$(agent orchestrator list-workflows --json | jq -r '.[] | select(.name=="my-workflow") | .id')
# Trigger it
agent orchestrator trigger-workflow "$WORKFLOW_ID"
For label-driven workflows, the quickest way to test end-to-end is to apply the
research-agent (or other) label to a real issue and watch the stream:
gh issue edit <number> --repo geoffjay/agentd --add-label "research-agent"
agent orchestrator stream --all
Tear down after testing¶
Human approval gates¶
These operations must never be performed by an agent without explicit human instruction.
Full reference: docs/planning/autonomous-pipeline-gates.md.
| Operation | Why |
|---|---|
git-spice auth login |
Interactive OAuth - cannot be scripted |
Modifying .agentd/agents/*.yml |
Changes agent behavior for all future runs |
Modifying crates/orchestrator/src/ core |
Risk of breaking the pipeline |
git push --force to trunk branches |
Destructive, irreversible |
| Deleting branches, issues, or milestones | Destructive |
| Production deployments | Human sign-off required |
| Adding new external service integrations | Architectural decision |
Related¶
- Pipeline State Machine - full label reference and lifecycle
- Research Agent - example of a specialist agent
- Templates Reference - complete YAML schema with all fields
- Tool Policies - tool restriction modes and approval flow
- Communication Guide - rooms, messages, and participants
CLAUDE.md- authoritative project conventions for all contributors