Responsibility map
Say which agent or person owns which topic, look the owner up before you send a request, and let agent-notify refuse a request that went to the wrong address.
Added in v0.221.11 A role address such as worker@ACME names who works a
project, not who owns a topic. Mail about game assets can end up at the
infrastructure integrator because the assets are stored on infrastructure,
while the session of the games project owns them. A project key is not a topic.
The responsibility map closes that gap: it records who owns what, agents
look it up before they send, and agent-notify catches a request that is
addressed to someone else.
The map
The map is a list of workspace-level entries. Each entry has:
| Field | Meaning |
|---|---|
| Topic | The name of the area, unique and case-insensitive. |
| Description | One or two sentences on what the topic covers. |
| Keywords and aliases | Words people and agents use for it. |
| Resources | Where the topic lives: {kind, value} with kind project, host, repo, path or other. |
| Owner address | The role address agents answer to, for example worker@ACME. |
| Human owner and deputy | Users. The deputy takes over when the owner is away. |
Every internal member and every agent can read the map; external users get 403.
Writing needs the admin:agents:write permission. A topic that already exists
answers 409, a human owner or deputy that is not a user answers 400. Every
write is audited as responsibility.created, responsibility.updated (with
the changed fields before and after) or responsibility.deleted. The map is
part of the full backup. The map ships empty: an operator enters the entries of
the workspace after the update.
Look up an owner
orboto owner "asset pipeline for the game builds"
orboto owner "backup host" --target integrator@INFRA --limit 3 --jsonThe lookup ranks the entries for a topic or free text:
- A hit on the topic, a keyword or a resource always ranks before any embedding score. The topic counts twice, every keyword, alias and resource once.
- A word matches exactly, as a plural
s, or as a close prefix when the shorter word has five letters or more (assetandassets,serverandservers).portdoes not matchportal, andhostdoes not matchhosting. - The embedding side is asked only when no keyword entry wins alone and an
embedding provider answers.
semantic: falsein the answer means it was needed and no provider answered. - Each match carries
score,reason(topic,keyword,resourceorembedding),matched(the terms that hit) androutes. A keyword hit always routes; an embedding-only match routes from a similarity of 0.55 and is not listed below 0.3.
With --target the answer also carries mismatch, the hint that the target is
not the owner.
Who answers to the owner
orboto who --for "asset pipeline for the game builds"who --for resolves the text the same way and prints the owner (the best match,
or null) and only the live sessions that answer to the owner address. An empty
list means a request there needs --queue --project ACME to wait for a
session.
Keep the map from the shell
orboto owner list
orboto owner set "Game assets" --owner worker@GAMES \
--keywords assets,textures,models --resource project:GAMES --resource path:/srv/assets \
--human maria@example.com --deputy jon@example.com
orboto owner rm "Game assets"owner set creates the topic or changes it. --human and --deputy accept
none to clear them. owner rm takes the topic or the entry id. These three
need admin:agents:write; the lookup does not.
Misaddressed requests
agent-notify checks every request (never info, complete or error).
The subject and the outcome are resolved against the map. When the best entry
routes and names an owner that the target is not, the request is misaddressed.
The target is not the owner when it is another role address, a session that
does not answer to the owner address, or an account none of whose live sessions
answers to it, unless that account is the human owner or deputy of the entry.
orboto agent-notify worker@INFRA "Rebuild the texture atlas" --kind request --outcome "Atlas rebuilt and published"
# refused: owner is worker@GAMES (topic "Game assets"), exit code 2
orboto agent-notify worker@INFRA "Rebuild the texture atlas" --kind request --outcome "Atlas rebuilt and published" --route
orboto agent-notify worker@INFRA "Rebuild the texture atlas" --kind request --outcome "Atlas rebuilt and published" --force-target| Flag | Effect |
|---|---|
| none | The CLI and the MCP tool refuse with 409 errors.agents.owner_mismatch. The answer names the owner, the target, the topic, the human owner and the full hint. The CLI prints it and exits 2; MCP returns a tool error that names both ways on. |
--route | Sends the request to the owner's role address instead, to every live session of that role on the owner's project. 409 no_recipient when there is none, unless --queue. The answer carries ownerHint.routed: true. |
--force-target | Skips the check and sends to the address you named. |
A plain REST call without ownerCheck sends the request and returns the
ownerHint next to the result, so an older client still hears about it.
Session start
orboto session-start prints a Responsibilities block after the Knowledge
block: the entries whose owner address or project resource names one of the
projects the session declared, the count of the rest, and a pointer to
orboto owner. A session without a scope gets the count and the pointer. An
empty map prints nothing. The project primer carries the same block as its
responsibilities section.
REST, MCP and the admin page
| Surface | How |
|---|---|
| REST read | GET /responsibilities, GET /responsibilities/:id, GET /responsibilities/resolve?q=<text>&target=<addr>&limit=N, GET /responsibilities/block?projectKeys=K,K |
| REST write | POST /responsibilities, PATCH /responsibilities/:id, DELETE /responsibilities/:id |
| Who answers | GET /v1/agent/who?for=<text> |
| MCP | orboto_who with for, or orboto_api_call for the other routes. orboto_agent_notify refuses a misaddressed request. |
| In-app chat | The orboto_owner tool |
| Admin | Admin -> Agents -> Responsibilities: lookup, table, add, change and remove. The write controls need admin:agents:write. |
See also
- Sessions, scope and the wake ledger - the scope rule that decides which sessions receive a message.
- Session origin and state - what
orboto wholists.
Session origin and state
What each session row says about the process it belongs to, how live, quiet and orphaned are decided, how to end a session, and what the reaper and a re-login do.
Comment events
How a comment on a ticket reaches the assignee's live agent sessions as mail, when it counts as a request, and how to switch it off per session.