Who's allowed to do what, and who's accountable, on a team of humans and AI agents: a machine-checkable RACI charter + linter.
Project description
AgenRACI — who's allowed to do what, and who's accountable, on a team of humans and AI agents
When an AI agent does something on your team — ships code, sends a message, spends money — and no human pressed the button, who is accountable? AgenRACI is one plain-language file that answers that up front, for every kind of action: who may do it, who signs off, and who owns the outcome.
For decades, teams have used RACI — a simple chart of who is Responsible, Accountable, Consulted, and Informed for each kind of work. RACI quietly assumes a person starts every task. AI agents break that assumption: they can act on their own, but someone human must still answer for what they do.
AgenRACI brings RACI into the age of AI agents. You write one file — a charter — that lists, for each type of action on your team:
- who does it (Responsible),
- who is accountable (exactly one person or role),
- who must be consulted or kept informed,
- who has to approve it first, and
- what happens if the one who should act is unavailable.
A built-in checker reads the charter and flags the gaps before they bite: an action with no one accountable, two people who both think they're in charge, or an approval step that could quietly stall forever.
pip install agenraci
agenraci init # writes a commented charter.yaml to edit
agenraci validate charter.yaml # check it holds together
Cloned the repo instead? Validate a bundled example directly:
agenraci validate examples/sprout/charter.yaml.
Prefer to try it without installing? A paste-and-check playground runs the
real checker in your browser (nothing uploaded) — see
docs/playground/.
New here? Start with the essay: Why AgenRACI — the accountability gap, why classic RACI breaks under agentic AI, and how this fits ISO/IEC 42001 and the EU AI Act.
Already running agents (LangGraph, CrewAI, Claude subagents)? The cookbook From a running agent team to a charter shows what to literally write, mapping graph nodes → roles → accountable owners.
See it catch a gap
A charter where two roles both think they're accountable for shipping code — the checker catches it (rule R1), and the one-line fix passes:
$ agenraci validate docs/demo/charter-broken.yaml
✗ R1 single accountable
- A2_ship_code: has 2 accountable roles (builder, reviewer) — exactly one is required.
FAIL — 1 issue(s) found.
$ agenraci validate docs/demo/charter-fixed.yaml
✓ R1 single accountable
PASS — charter is a valid operating constitution.
Full walkthrough + a recordable GIF script: docs/demo/.
What AgenRACI is (and isn't) yet
Today, AgenRACI helps you write the charter and checks that it holds together. You get:
- a clear format for the charter file,
- an automatic checker that catches gaps, conflicts, and approval steps that could deadlock,
- a worked example and a blank template to start from.
AgenRACI does not run your team — yet. It doesn't (today) intercept actions or enforce approvals at the moment they happen. Tools like LangGraph, CrewAI, and HumanLayer already handle running agents and pausing them for sign-off. AgenRACI sits one level up and answers what they don't: on this specific team, who is allowed to do what, and who breaks a tie. Turning the charter into live, enforced approvals is the next milestone on the roadmap — not a claim about today.
The gap we fill
Today, RACI is mostly applied at the governance level — the boardroom and compliance question of "who answers for the AI system as a whole" (the concern behind standards like ISO/IEC 42001 and the EU AI Act). What's missing is the operating level: a precise, machine-checkable charter for the day-to-day, where the AI agents themselves hold real roles and the rules can be verified by a tool instead of living in a slide deck. That everyday accountability — for the exact moment an agent acts on its own — is what AgenRACI covers.
The core model (three independent questions)
Most "who does what" confusion comes from mixing up three different questions. AgenRACI keeps them separate:
| Question | What it asks | Example |
|---|---|---|
| Function | What do you do? | Orchestrate, Build, Advise, Investigate, Review, Watch |
| Permission | What may you touch? | edit_code, merge, deploy, spend, … granted or explicitly denied |
| Authority | Whose call wins in a conflict? | Each action's accountable, plus gate escalate_to for timeouts |
The proof they're separate: a domain expert can be accountable for a fact, denied the right to touch code, yet able to block a merge on correctness grounds — all at once, none implying the others.
Roles are defined once; members are assigned
You don't rewrite the rules for every agent. Define a small set of roles (orchestrator, engineer, domain expert, researcher, reviewer, monitor) once, then assign humans and agents to them. Adding an agent is a one-line appointment, not a new rulebook.
One accountable per action — no gaps, no turf wars
List the types of action in your project (not individual tasks), and require each to have exactly one accountable role. Nobody accountable = a gap; two people accountable = a turf war. The checker catches both.
Escape hatches so the rules never deadlock
People aren't always online — and neither are agents. So every approval step must
say what happens on timeout (block, escalate to someone, or, only for
explicitly low-risk actions, proceed), and must have a break_glass emergency
path. Any blocked-but-confident actor gets a suggestion_route so their input
isn't silently dropped. proceed on timeout is a guarded opt-in — allowed only on
an action explicitly marked low-risk — so "low risk" can never become a quiet
backdoor for an agent to act unsupervised.
The checker (v0.1)
| Rule | Checks |
|---|---|
| R1 | single accountable — every action type has exactly one accountable |
| R2 | coverage — no unused permissions; no action uses an undeclared permission |
| R3 | no contradiction — no role both grants and denies the same permission |
| R4 | gate completeness — every approval step has a timeout rule + emergency path; every blocking deny has a suggestion_route |
| R5 | low-risk gating — proceed on timeout only on an action marked low-risk |
| R6 | acyclic authority — gate escalate_to timeouts never form a loop, so a decision can't escalate forever without anyone able to settle it |
CLI
agenraci init [path] # write a commented starter charter (default: charter.yaml)
agenraci validate <charter.yaml> [more.yaml...] # parse + check, with a per-rule report
agenraci validate --explain <charter.yaml> # ...and a plain-language fix under each failure
agenraci validate --format github <charter> # ...and ::error annotations for GitHub Actions
agenraci schema # print the charter JSON Schema (for editor autocomplete)
agenraci compile --target claude <charter> -o . # emit .claude/agents/ definitions + a CLAUDE.md snippet
agenraci compile --target github <charter> # emit CODEOWNERS + branch-protection checklist + applyable protection.json
agenraci compile --target humanlayer <charter> # placeholder in v0.1
agenraci compile --target langgraph <charter> # placeholder in v0.1
The claude target makes the charter operative for a Claude Code
team: it generates one .claude/agents/<member>.md per agent member — role
boundaries, explicit "never do X" denials, who signs off on what — plus a
governance snippet for CLAUDE.md. Two people collaborating with their own
agents compile the same charter and both sides' agents carry the same rules.
(Still honest scope: these are config files the runtime already reads, not
runtime interception. This repo's own .claude/agents/ follows exactly this
pattern.)
A freshly init'd charter carries a # yaml-language-server: $schema= line, so
editors with the YAML language server (e.g. VS Code + the Red Hat YAML
extension) give you autocomplete and inline validation as you type.
Keep the charter honest in CI
A charter only protects you if it stays valid as it changes. Two ways to enforce that automatically:
GitHub Action — fail a PR that breaks the charter:
# .github/workflows/charter.yml
on: [push, pull_request]
jobs:
charter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jing-ny/agenraci@v0.1.1
with:
charter: charter.yaml # a path, or a glob like 'governance/*.yaml'
A failing charter shows up as a file-level annotation in the PR's "Files
changed" tab (the Action runs validate --format github), not just buried in
the run log.
"charter checked" badge — once that workflow is in place, show it off in your README so every reader can see the charter passes:
[](https://github.com/<you>/<repo>/actions/workflows/charter.yml)
(This repo wears its own: the badge at the top runs AgenRACI's Action on
governance/charter.yaml — we govern ourselves with the same check.)
GitHub Action (verify) — check that your repo's branch protection actually matches what the charter declares:
# .github/workflows/charter.yml (add a second job alongside the validate job)
verify:
runs-on: ubuntu-latest
continue-on-error: true # see auth caveat below
steps:
- uses: actions/checkout@v4
- uses: jing-ny/agenraci/verify@<ref>
with:
charter: charter.yaml # path to your charter
repo: ${{ github.repository }} # OWNER/REPO (default)
branch: main # protected branch (default)
python-version: "3.12" # Python version (default)
This Action runs agenraci verify --target github against your repo's live
branch protection and CODEOWNERS. It exits 1 if the repo drifts from the
charter (for example, a required approver was removed from CODEOWNERS), and
exits 0 if the branch enforces at least what the charter declares. The
charter is a floor: a repo whose protection is stricter than the
minimum the charter requires still passes. A gated action whose accountable
role has no human member is reported as unenforceable — GitHub code owners
must be human — neither pass nor fail.
Exit codes: 0 = clean, 1 = drift, 2 = could-not-check.
Scope reminder. The verify Action is read-only. It never POSTs to GitHub and never intercepts or enforces actions at runtime. It tells you whether drift exists; it does not fix it.
Auth caveat. Reading live branch protection via gh api requires admin
permission on the repo. The default GITHUB_TOKEN usually does not have
it, so an out-of-the-box run typically exits 2 (could-not-check), not 1
(drift). To get a real drift check, supply an admin-scoped token (for example
a PAT stored as a repository secret):
env:
GH_TOKEN: ${{ secrets.ADMIN_PAT }}
Without that token, continue-on-error: true prevents a spurious could-not-check
exit from turning the build red and being misread as a charter violation. This
is exactly what AgenRACI's own dogfood verify job does.
For a step-by-step walkthrough of the full compile → apply → verify loop (with worked examples and exit-code explanations), see Check your repo.
pre-commit hook — catch it before it's even committed:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/jing-ny/agenraci
rev: v0.1.1
hooks:
- id: agenraci-validate # checks staged charter.yaml / charter.yml files
agenraci validate takes one or more paths, so a single call checks every
charter in the repo and exits non-zero if any fails. For a step that another
tool or dashboard should parse, add --format json to get one machine-readable
object per charter ({charter, project, ok, rules: [...]}) instead of the human
report — one JSON object per line when you pass several charters. Add --explain
too if JSON consumers should receive each failing rule's plain-language fix as an
explanation field on the finding objects.
Code-scanning alerts — --format sarif emits a single SARIF 2.1.0 document
you can upload so charter failures show up in a repo's Security tab. Add these
steps to a job that has agenraci installed (pip install agenraci):
- run: agenraci validate governance/charter.yaml --format sarif > charter.sarif
continue-on-error: true # upload the report even when the charter fails
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: charter.sarif
(Findings are file-level: the checker points at a target — an action or role name — not a source line, so each alert lands on the charter file.)
Repository layout
agenraci/
├── README.md # this file
├── SPEC.md # the three questions, RACI rules, file format, checker rules
├── agenraci/ # the Python package (schema, checker, cli, connectors,
│ # and the starter template `agenraci init` writes)
├── governance/ # AgenRACI's own charter — the project governs itself
├── examples/autopilot/ # ★ flagship: an autonomous coding team (1 human + 4 agents)
├── examples/hello-world/ # the smallest meaningful charter (1 human + 1 agent)
├── examples/blog/ # one step up: a gate + separation of powers (1 human + 2 agents)
├── examples/sprout/ # a complete worked example (2 humans + 6 agents)
├── examples/relay/ # an all-agent worked example (5 agents, 0 humans)
└── tests/ # one test per rule + known-good / known-bad charters
Roadmap
- v0.1 — write it and check it. The charter format, the checker (R1–R6) with
validate --explainplain-language fixes, worked examples (the Autopilot flagship + others), a template, a GitHub Action, and a pre-commit hook. - v0.2 — GitHub enforcement loop. ← you are here.
agenraci verify --target githubchecks a live repo's branch protection and CODEOWNERS against the charter and fails CI on drift — offline--settingsmode (#60) and live--repomode viagh api(#61). The companionverifyGitHub Action (#62) drops into any workflow in two lines (dogfooded here; live branch-protection reads need admin scope, so the dogfood job usescontinue-on-error).agenraci compile --target github(#63) now also emits a directly-applyable classic branch-protection PUT JSON, a ready-to-rungh apicommand, and a verify round-trip step — closing the compile → apply → verify loop. A step-by-step cookbook (#65) walks the whole loop end-to-end. Still no runtime interception — verify, don't intercept. - v0.3 — first runtime connector. A working HumanLayer connector that turns
charter gates into real approval pauses, plus a richer authority graph beyond
gate
escalate_toedges (standing veto relations). - v0.4 — LangGraph connector + a small web view that renders the chart so non-engineers can read it.
- v0.5 — author ergonomics. Inline checker findings in an editor, and a reference mode that explains any rule on demand.
FAQ
Isn't this just RBAC?
No. Permission ("what may you touch") is only one of AgenRACI's three axes.
Role-based access control answers that one question and stops there. AgenRACI also
separates Function (what you do) and Authority (whose call wins in a
conflict), and — the part RBAC has no concept of — it centers a single
accountable owner for each type of action. RBAC can tell you an agent is
allowed to call deploy; it can't tell you who answers for the deploy, who had to
sign off first, or what should happen if that approver goes dark. A charter can be
denied a permission yet still be accountable for the outcome — those are different
axes, and conflating them is exactly the gap AgenRACI exists to close.
Why not just use HumanLayer / LangGraph / CrewAI? Use them — they're solving a different layer. Those frameworks run agents and can pause them to wait for a human sign-off. AgenRACI sits one level up: it's the file that says, for this specific team, who is allowed to do what, who owns each outcome, and who breaks a tie — independent of which runtime you use. The charter is framework-agnostic on purpose. Turning a charter into the live gates those tools enforce (starting with a HumanLayer connector) is on the roadmap; today AgenRACI defines and checks the rules those runtimes would enforce.
Is this vaporware?
No. v0.1 writes and checks a charter today: a real file format, an automatic
checker with rules R1–R6, worked examples, and a template — all of which you
can run from a clone of this repo (pip install -e . then
agenraci validate examples/sprout/charter.yaml). What it does
not do yet is intercept actions or enforce approvals at runtime; that's stated
plainly in What AgenRACI is (and isn't) yet
above and tracked on the roadmap, not dressed up as a current capability.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agenraci-0.2.0.tar.gz.
File metadata
- Download URL: agenraci-0.2.0.tar.gz
- Upload date:
- Size: 53.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28e0b944937fbe727bef35b4125ee267f7b468290e755eb732a915b41403bd3d
|
|
| MD5 |
75f4d316d5fde09420584d43073fcdf6
|
|
| BLAKE2b-256 |
937d7001d0a3435c13e6d38e62d309abe7f7070d95a1247e681b7143f3c65492
|
Provenance
The following attestation bundles were made for agenraci-0.2.0.tar.gz:
Publisher:
publish.yml on jing-ny/agenraci
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenraci-0.2.0.tar.gz -
Subject digest:
28e0b944937fbe727bef35b4125ee267f7b468290e755eb732a915b41403bd3d - Sigstore transparency entry: 1855442757
- Sigstore integration time:
-
Permalink:
jing-ny/agenraci@024d451eee6f0c8b0f7bb7141f5f2595e0027575 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/jing-ny
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@024d451eee6f0c8b0f7bb7141f5f2595e0027575 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agenraci-0.2.0-py3-none-any.whl.
File metadata
- Download URL: agenraci-0.2.0-py3-none-any.whl
- Upload date:
- Size: 40.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88c91a9978cca6d28fcbeaa77a389e950171f330f7c4d5c806cfe9ce337d833b
|
|
| MD5 |
f60a646e30e10f092c863d1e0707f69a
|
|
| BLAKE2b-256 |
b28de29e2029b34cf7097666d1baa920de0357e565bd4797be9cfb2fb485268c
|
Provenance
The following attestation bundles were made for agenraci-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on jing-ny/agenraci
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agenraci-0.2.0-py3-none-any.whl -
Subject digest:
88c91a9978cca6d28fcbeaa77a389e950171f330f7c4d5c806cfe9ce337d833b - Sigstore transparency entry: 1855442784
- Sigstore integration time:
-
Permalink:
jing-ny/agenraci@024d451eee6f0c8b0f7bb7141f5f2595e0027575 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/jing-ny
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@024d451eee6f0c8b0f7bb7141f5f2595e0027575 -
Trigger Event:
push
-
Statement type: