Autonomous Pipeline - Human Approval Gates¶
This document defines which operations in the agentd autonomous pipeline require
human approval, which are configurable, and which always run without intervention.
Gates are enforced through the orchestrator's tool policy system and through
.claude/hooks/ PreToolUse hooks.
Gate Categories¶
ALWAYS HUMAN (cannot be automated)¶
These operations must never be performed by an agent without explicit human instruction. No tool policy override exists.
| Operation | Reason |
|---|---|
git-spice auth login |
Interactive OAuth - one-time per environment; cannot be scripted |
Changes to .agentd/agents/*.yml |
Alters agent behavior and permissions for all future runs |
Changes to crates/orchestrator/src/ core |
Risk of breaking the pipeline itself |
| Production deployments | Risk threshold requires human sign-off |
| Security-critical dependency changes | Flagged by auditor; may introduce CVEs |
| Merge conflict resolution (escalated by conductor) | Requires human judgment to avoid data loss |
| Adding new external service integrations | Architectural impact; may introduce new attack surface |
| Deletion of branches, issues, or milestones | Irreversible without git reflog; issues/milestones cannot be recovered |
git push --force or git reset --hard to trunk branches |
Destructive history rewrite |
Enforcement: The
.claude/hooks/destructive-protection.pyhook blocks destructive git/gh commands. Any change to.agentd/agents/orcrates/orchestrator/src/must go through a human-reviewed PR and cannot be committed directly by an agent running autonomously.
CONFIGURABLE GATES (default shown; can be adjusted via tool policies)¶
These operations are safe to automate in most cases but may require human oversight depending on environment or risk tolerance. Defaults represent the policy shipped in this repository.
| Gate | Default | Rationale |
|---|---|---|
| PR auto-merge (approved + CI green) | allow | Low risk when both conditions are met |
| Issue auto-close after branch merge | allow | Clean bookkeeping; reversible |
| Planner creating issues autonomously | allow | Issues are soft state; easy to close |
| Applying labels to issues/PRs | allow | Reversible; purely metadata |
New Cargo.toml dependency additions |
ask | Introduces new supply-chain risk |
Closing issues marked security |
ask | Human should verify fix before closing |
| PR auto-merge when CI is flaky (retry > 2) | ask | Flakiness may hide real failures |
Removing the needs-rework label |
allow | Conductor re-dispatches; worker acts |
Changing a gate: Edit the tool_policy block in the relevant agent YAML
(.agentd/agents/<agent>.yml) and re-apply with agent apply .agentd/.
ALWAYS AUTONOMOUS (no human approval needed)¶
These operations are safe and reversible enough that no approval gate is needed.
| Operation |
|---|
| Branch creation, switching, and deletion via git-spice |
| PR submission, updates, and stack navigation |
| Code review comments and requested changes |
Test writing and documentation updates within docs/ |
Memory read/write operations (agent memory *) |
Communication channel messages (agent communicate *) |
| Reading any file in the repository |
Running cargo build, cargo test, cargo fmt, cargo clippy |
Running gh issue list, gh pr list, and other read-only GitHub queries |
Applying needs-triage label to newly filed issues |
| Posting status digests to the operations room |
Tool Policy Configuration¶
Tool policies are declared in each agent's YAML under the tool_policy key.
They use glob/regex pattern matching against the command being executed.
Example - Conductor¶
tool_policy:
# Allow squash merges (controlled by merge-ready gate check)
- pattern: "gh pr merge * --squash *"
mode: allow
# Allow label changes (reversible metadata)
- pattern: "gh * --add-label *"
mode: allow
- pattern: "gh * --remove-label *"
mode: allow
# Block all force pushes - always human
- pattern: "git push --force*"
mode: deny
# Block deletions of issues or milestones - always human
- pattern: "gh issue delete *"
mode: deny
- pattern: "gh api repos/*/milestones/* --method DELETE"
mode: deny
# Ask before new Cargo dependency additions
- pattern: "cargo add *"
mode: ask
Example - Worker¶
tool_policy:
# Block modification of agent YAML files - always human
- pattern: "* .agentd/agents/*"
mode: deny
# Ask before adding new Cargo dependencies
- pattern: "cargo add *"
mode: ask
# Block force push
- pattern: "git push --force*"
mode: deny
# Block direct issue or milestone deletion
- pattern: "gh issue delete *"
mode: deny
Temporary Gate Override¶
To bypass a configurable gate for a single conductor run, use the
conductor-sync label with an override instruction in the PR body:
# Label the issue/PR
gh issue edit <number> --repo geoffjay/agentd --add-label "conductor-sync"
# The conductor reads the PR body for override instructions:
# OVERRIDE: allow cargo add serde_json (reason: pinning transitive dep)
The conductor checks the PR body for OVERRIDE: lines and relaxes the
corresponding policy for that run only. Overrides are logged to the operations
room for auditability.
Escalation Path¶
When the conductor cannot proceed autonomously because a gate blocks it:
- Conductor posts to the
engineeringroom: - Conductor leaves the PR labeled with the appropriate status (
needs-rework,needs-restack, ormerge-readypreserved). - Human resolves the gate condition and re-triggers via the appropriate label
(
conductor-sync,merge-ready,agent, etc.).
References¶
- Tool policy DSL:
docs/public/tool-policies.md - Pipeline state machine:
docs/public/pipeline-state-machine.md - Destructive protection hook:
.claude/hooks/destructive-protection.py - Coordination hook:
.claude/hooks/check-coordination.py