Organizations and roles
The org chart is the routing layer: organizations, departments, roles, actors, templates, and the rule that an org-owned mission is owned by a role.
An organization in Orgabot is a modeled org of humans and AI agents. Its defining property is that access is a capability a role holds: granted explicitly and audited, never ambient authority that everything inherits.
The pieces
| Piece | What it is |
|---|---|
| Organization | The top-level container. Bootstrap with orgabot organization bootstrap or the dashboard wizard. |
| Role | A seat in the org chart (CTO, engineer, QA, CISO…). Roles hold capabilities and authority. |
| Actor | Who fills a seat: a persistent agent (the default) or a person. Swappable at any time. |
| Department | An org-scoped business function grouping roles. Membership describes participation only; it grants nothing. |
| Template | A curated, additive and idempotent bundle of roles you layer onto the chart. It requests connections by category and grants nothing on its own. |
| Client / scope | Optional modeling of clients, so projects can be scoped internal or client. |
orgabot organization bootstrap --name "Acme"
orgabot organization template list
orgabot organization template install <org> <template-id>
orgabot organization agent create <org> <role-slug> [name]
orgabot organization assign <org> <role-slug> <actor-id>
orgabot organization project add <org> <project> --scope internalRoles are behavioral contracts, not labels
A role carries a mandate, procedures, expected artifacts, and an escalation path, and that contract is injected into the mission brief of every mission the role owns. A DevOps role is told it owns CI/CD, reliability, and recovery, and that production changes need evidence and rollback readiness. That is why routing to the right role changes the character of the work, not just its attribution.
Routing and delegation
For an org-mapped project, one AI step reads roles and capabilities and either selects a single role or produces a multi-role plan; sub-missions run supervised and roll up. --no-decompose forces single-role routing.
An org-owned mission is owned by a ROLE. The generic unattributed worker is sanctioned only when no organization maps the project, or when you pass --no-org. If an org maps the project and no role can be auto-selected, the mission holds and asks you to pick one. Silent fallback to a generic worker is a defect, not a convenience.Agents route through roles and capabilities before escalating. No agent may self-grant authority, and humans enter only where policy, risk, spending, reserved authority, or configuration requires them.
An organization store Orgabot cannot read is unknown, not empty. "No organization maps this project" is the one condition that permits the generic worker, so a storage failure must never be able to produce it: an unavailable operational store holds the mission and asks you rather than running it as an unattributed worker or as your own identity. Migrating that storage changes nothing about who may grant what: a role grant and a capability grant still pass the same authority checks, a connector permission is still the clamp of the App's own grant, the connector's provisioned ceiling, and the per-role grant, and connector secrets do not move.
Capability gaps and staffing
The Chief of Staff plans against the organization it actually has. The planner is shown every active role with its mandate and the connector authority it holds, and every node it proposes must be executable by one of those roles: a node that needs, say, visual design and source control on an organization where those are different roles is refused with the per-capability eligibility and re-planned, rather than becoming a gap on a mission that never needed one. It also prefers the smallest plan: a bounded change to one repository is one node for the role that can edit the code and open the pull request, with no separate specification, acceptance, or preview steps the request did not ask for.
When decomposition finds work no staffed role can cover, the gap is detected and durably held rather than quietly reassigned. The Chief of Staff creates an immutable, human-owner-reviewed staffing proposal; an approved proposal is carried through the ordinary governed role, authority, connector, grant, verification, and idempotent resume gates. The owner remains the approval authority for that organizational change.
A gap asks for exactly what is missing. The capabilities the nearest role already holds are left out of it, a connector is requested as a connector grant rather than as a tool, and a tool id that is not in the governed-tool registry is refused when the gap is created instead of failing after you have approved it. A connector granted at write already covers a read requirement, so no approval is raised to widen access a role has.
An agent cannot file a capability gap by itself and must ask instead, naming the gap and the role that should own it.
The executive view
Business questions get business answers, from the same records the engineering surfaces use:
orgabot organization home <org> # asked, delivered, needs attention, on track, cost
orgabot organization attention <org> # needs you / handled automatically / for awareness
orgabot organization health <org> # department health and what materially changed
orgabot organization risks <org> # what is at risk, what Orgabot is handling, the one action
orgabot organization figures <org> # every business figure with provenance and freshness
orgabot organization milestones <org> # accountable commitments and explicit forecastsProvenance and freshness ride along with each figure on purpose: an inferred number must never be presented as authoritative organizational truth.
Duties: recurring role work
A duty is a scheduled, recurring objective a role performs:
orgabot role duty add <org> <role> [<project>] "<objective>" --cron "<expr>" | --interval <dur>
orgabot duty list <org>
orgabot duty run-due [<org>] [--now ISO] [--dry-run]run-due is the entrypoint a launchd or cron job calls. There is no always-running Orgabot daemon: if nothing invokes run-due, no duty ever fires.
The organization argument is optional: with none, run-due runs every active organization in turn. That is what the installed host timer calls, so a new organization is covered the moment you create it, with no reinstall.
A tick with nothing due writes nothing. run-due reads the organization store, and it saves it only when a duty actually ran, so a timer firing four times an hour on a quiet install is purely an observation. That matters if you are ever repairing organization state by hand: an unconditional writer would race your repair and re-save whatever it had already loaded.
--dry-run reports which duties are due (and what each would run) without recording a mission, advancing the schedule, or launching a worker. --help/-h prints usage and runs nothing, and an unknown flag is refused rather than silently ignored.
Each scheduled fire launches its worker with its own fresh mission identity, linked back to the governing organization mission record. If a launch itself is refused (an id that could not be resolved, most often), the run is still recorded - the duty's schedule already advanced - but orgabot duty list marks it ! last run failed to launch with the reason, so a duty that ran but never actually started a worker is never left to look like an unexplained silent hold.
Install that timer with orgabot scheduler install (launchd on macOS, cron on Linux), inspect it with orgabot scheduler status, and use orgabot scheduler reinstall if orgabot doctor reports an entry left under the old com.orka / # ORKA BEGIN spelling. reinstall removes it and rewrites the entry under the current one, in one idempotent step.
Who answers for what
Membership, authority, and responsibility are three different things, and Orgabot keeps them apart on purpose:
- Membership is which department a role sits in. It grants nothing.
- Authority is what a role may actually do: capability packs, tool grants, connector grants, each explicit and separately revocable.
- Responsibility is who answers for an outcome. It grants nothing either.
orgabot responsibility assign acme --subject department:dept_eng --role role_lead --level accountable
orgabot responsibility list acme --subject department:dept_eng
orgabot responsibility close acme resp_abc123Four levels: accountable, responsible, consulted, informed. At most one accountable role per subject over any overlapping period - two is not a stricter arrangement, it is an unanswered question, and it surfaces at exactly the wrong moment, when something has gone wrong and two roles each believe the other has it. Assigning a second is refused rather than quietly replacing the first, because reassigning accountability is a decision somebody makes. Back- dating one does not get around it: the check compares periods, not instants.
An assignment ends by being closed, never removed. "Who was accountable when this happened" is the question an incident review asks, and a deleted record answers it wrongly with total confidence.
Councils
Some decisions a single role may not make alone.
orgabot council create acme --slug security --name "Security council" \
--charter "Decides risk acceptance and connector adoption" \
--quorum 2 --escalate-to role_ciso --rights risk_acceptance,connector_adoption
orgabot council seat acme council_abc --role role_lead --seat chair
orgabot council decide acme council_abc --kind risk_acceptance --participants role_lead,role_secA council decides the kinds it names and nothing else: its authority does not grow because somebody routed a new question at it. A decision below quorum is held and escalated, never made by whoever showed up - that is the difference between a council and a suggestion box. Observers and people who simply turned up never count toward quorum.
Seats end (orgabot council unseat) and councils dissolve (orgabot council dissolve) rather than being deleted, so a role that left stops counting toward quorum while the decisions it took part in stay traceable to a body that existed.
Sitting on a council grants nothing. Every change to a responsibility or a council is recorded on the organization's append-only ledger - including a decision that was HELD, because a hold that left no trace cannot be told later from a question nobody ever brought.
Trust, decisions, and handing work to a person
Trust is advisory. A trust profile records how much supervision a role's work is judged to need. Nothing reads it to decide what a role may do - authority stays capability packs, tool grants, and connector grants, each explicit and separately revocable, and a test asserts no grant path can even see the model. A score that quietly widened what a role could do would be an authority change with no grant behind it: no approval, no ledger entry naming it, nothing for an audit to find except a number that drifted.
orgabot trust set acme --role role_a --level trusted --basis "six clean ships"
orgabot trust evaluate acme --role role_a --kind mission_outcome --evidence mission:m1 --summary "no review findings"
orgabot trust history acme --role role_aA profile is versioned, never edited, so a level can be traced to the evidence that changed it. An evaluation must cite something that happened - a mission, a review, a gate decision. An opinion is not evidence, and this model would launder one into a number.
Decisions carry what they were weighed against.
orgabot decision record acme --question "Which database?" \
--alternatives "sqlite=Local SQLite;postgres=Managed PostgreSQL" \
--chose sqlite --because "local-first" --basis "ADR 0063" \
--rejected "postgres=needs an async interface we do not have"
orgabot decision observe acme dec_abc --summary "held up under load"At least two alternatives, and a reason each rejected one was rejected. With one option it is a record of what happened, and the question it exists to answer later - what else was considered, and why not - has no answer. The outcome is observed separately and later, and its absence is visible: a decision nobody followed up on must not read like one that worked. The first observation is never overwritten.
A human is not an agent executor.
orgabot handoff offer acme --role role_a --to actor_person --subject "Review the security posture"
orgabot handoff advance acme hum_abc --to acceptedNothing is launched, no worker is spawned, no verification gate runs. The transitions belong to the person, and they can decline or hand work back - neither of which a worker Orgabot spawned can do, which is exactly why modelling a person the way a mission is modelled would be pretending. Declined, handed back, and completed are terminal: the work is offered again as a new record rather than revived, so the first ask stays on the history.
Model and reasoning effort
Every place you pick a model, you can pick the reasoning effort beside it: Low, Medium, High, Extra high, Max, and Default, which means the provider's own effort and sends no flag at all.
orgabot organization role-executor set acme controller claude-code --model opus --effort maxNot every provider has a word for every level. Codex and Grok stop at high, so Extra high and Max clamp there. The picker offers them anyway, because an effort pinned across the organization should not vanish when one role runs on a different provider, but it says what will happen: the option reads Max (runs as high). Choosing a level the provider then quietly overrides is worse than having fewer choices, because you believe you configured something.
A running mission's card shows the effort next to the model, and shows the clamp when one applies (max → high effort). A mission that took the provider's default shows no effort at all rather than the word "default", which would state a choice nobody made. Missions that ran before effort was recorded show nothing either, for the same reason.
Some providers take no effort setting at all. The API providers (Anthropic, OpenAI, OpenRouter) do not read one today, so the picker offers only Default for them and says so, and a mission running on one shows no effort on its card. Offering a level that gets dropped on the way to the model is the same failure as offering one the provider silently overrides.
Speed modes are not configurable. Some providers offer a faster mode in their interactive apps, but the CLIs Orgabot spawns expose no flag for it, so there is nothing for Orgabot to set. It is not offered rather than offered and ignored.
The executor chain
A role's executor is not one choice but an ordered chain: a primary preference and the fallbacks a mission drops to when the primary's quota is exhausted. The dashboard shows it as one row of boxes, numbered in the order they are tried, and the model behind it is one ordered list.
Reordering moves one box. The arrows on a box move it one position earlier or later, and dragging a box by its header drops it into any position, with the target box highlighted as you pass over it. The left arrow on the SECOND box promotes it to primary and demotes the primary into the slot it just left, one position, never to the end of the chain. Every reorder is a single move of a single box, so no reorder can duplicate a box or lose one.
Fallbacks are stored with the role's own executor, so a role whose primary is Default (inherit) has nowhere to keep them. Pin a primary provider first; the control says so rather than letting the save fail.
Each box carries its own model AND its own reasoning effort. A fallback that runs the mission runs it at some effort, so the setting is on every box and not only the primary.
Each box carries its provider's mark, so a chain of four is readable at a glance instead of being four identical grey boxes.
An API key belongs to the box it was entered on. Moving a box carries its stored key with it, so reordering never hands one rung's credential to whichever rung happens to land on its old position, and never asks you to retype a key you already gave Orgabot.
Where the model list comes from
The model dropdowns start from a list built into Orgabot, which by itself goes stale the day a vendor ships a new version. So the picker also reads the vendor's own published model list and offers what it finds beyond the built-in one. The line above the chain says when that list was last read, and the Refresh button beside it reads it again.
Reading it is an explicit action, never something a page load does: it spends your own vendor API key, and Orgabot does not spend a credential to paint a screen. A refresh that fails keeps the list you already had and says what went wrong, because replacing a working list with an empty one is worse than a stale one.
Discovery needs a key for the vendor, which Orgabot takes from the credentials you already gave it (the Ask Orgabot configuration, a role's API-key executor, or the vendor's usual environment variable). Grok has no key-based provider here, so its list stays the built-in one, and any model id can still be typed in through Custom….
The CLI aliases are labelled for what they are. Opus (latest) is whatever the installed CLI resolves that alias to today; Opus 5 is that exact version. An alias labelled with a version number is a claim that quietly stops being true.
Portfolios, programs, and shared metrics
Milestones and key results already exist. What was missing is the layer that says which milestones belong to one effort, and a metric definition every surface can reference instead of each inventing its own unit.
orgabot metric define acme --slug arr --name "Annual recurring revenue" \
--unit usd --direction increase --source connector:conn_stripe --freshness 24
orgabot portfolio create acme --slug growth --name Growth --intent "grow revenue" --metrics arr
orgabot program create acme --portfolio pf_abc --slug self-serve --name "Self serve" --milestones ms_1,ms_2
orgabot program rollup acme prog_abcRecord what you observe with orgabot metric record acme --slug arr --value 120000; orgabot metric list then shows each definition beside whether its latest reading is current, stale, unobserved, or unusable.
A metric needs a source and a freshness bound. Without a source it is a number nobody can re-derive, which is a number you have to take on faith at exactly the moment you are deciding something. Without a freshness bound, a reading from last quarter reports identically to one from this morning. A metric with no reading at all is unobserved - neither stale nor zero, because rendering "nobody looked" as 0 would show a metric moving in the good direction. A reading whose age cannot be decided - timestamped in the future, or with a garbage timestamp - is unusable, which is its own answer again: calling it current would let clock skew mask a metric nobody has looked at in months, and calling it unobserved would stop anyone hunting the connector that is actually broken.
A program references milestones; it never writes them. Milestone authority and forecast semantics are preserved by adding no second writer, and the rollup is a projection. A program with no milestones reports null progress rather than 0%: it has not made no progress, it has nothing to measure.
A program belongs to exactly one portfolio. Two would mean two sets of priorities. Adding one to a closed portfolio is refused rather than reopening it silently.
Accountability is not a field on either record. It is a responsibility assignment on portfolio:<id> or program:<id>, so there is one answer to who is accountable - and it refuses two accountable roles over one period, keeps the history when one changes, and lands both facts on the ledger. A second owner field would have none of that.