agentcorp-broker 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/CONTRIBUTING.md +20 -0
  3. package/LICENSE +201 -0
  4. package/README.md +250 -0
  5. package/SECURITY.md +23 -0
  6. package/dist/audit.d.ts +25 -0
  7. package/dist/audit.js +203 -0
  8. package/dist/audit.js.map +1 -0
  9. package/dist/broker.d.ts +103 -0
  10. package/dist/broker.js +805 -0
  11. package/dist/broker.js.map +1 -0
  12. package/dist/cli.d.ts +2 -0
  13. package/dist/cli.js +712 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +3 -0
  16. package/dist/config.js +41 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/console/console.css +794 -0
  19. package/dist/console/console.js +802 -0
  20. package/dist/console/index.html +309 -0
  21. package/dist/credentials.d.ts +16 -0
  22. package/dist/credentials.js +72 -0
  23. package/dist/credentials.js.map +1 -0
  24. package/dist/database.d.ts +119 -0
  25. package/dist/database.js +1356 -0
  26. package/dist/database.js.map +1 -0
  27. package/dist/diagnostics.d.ts +44 -0
  28. package/dist/diagnostics.js +357 -0
  29. package/dist/diagnostics.js.map +1 -0
  30. package/dist/errors.d.ts +5 -0
  31. package/dist/errors.js +14 -0
  32. package/dist/errors.js.map +1 -0
  33. package/dist/index.d.ts +23 -0
  34. package/dist/index.js +15 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/mcp.d.ts +3 -0
  37. package/dist/mcp.js +215 -0
  38. package/dist/mcp.js.map +1 -0
  39. package/dist/migrations.d.ts +13 -0
  40. package/dist/migrations.js +266 -0
  41. package/dist/migrations.js.map +1 -0
  42. package/dist/policy.d.ts +22 -0
  43. package/dist/policy.js +33 -0
  44. package/dist/policy.js.map +1 -0
  45. package/dist/server.d.ts +49 -0
  46. package/dist/server.js +529 -0
  47. package/dist/server.js.map +1 -0
  48. package/dist/stdio-adapter.d.ts +230 -0
  49. package/dist/stdio-adapter.js +406 -0
  50. package/dist/stdio-adapter.js.map +1 -0
  51. package/dist/tui.d.ts +26 -0
  52. package/dist/tui.js +291 -0
  53. package/dist/tui.js.map +1 -0
  54. package/dist/types.d.ts +355 -0
  55. package/dist/types.js +85 -0
  56. package/dist/types.js.map +1 -0
  57. package/docs/ARCHITECTURE.md +119 -0
  58. package/docs/README.md +37 -0
  59. package/docs/RELEASING.md +228 -0
  60. package/docs/ROADMAP.md +112 -0
  61. package/docs/cli-reference.md +133 -0
  62. package/docs/dogfooding-report.md +83 -0
  63. package/docs/getting-started.md +228 -0
  64. package/docs/guides/antigravity-setup.md +84 -0
  65. package/docs/guides/claude-cursor-setup.md +76 -0
  66. package/docs/guides/codex-setup.md +75 -0
  67. package/docs/guides/human-console.md +177 -0
  68. package/docs/mcp-tools-reference.md +235 -0
  69. package/docs/policy-guide.md +105 -0
  70. package/examples/org.toml +65 -0
  71. package/package.json +68 -0
@@ -0,0 +1,177 @@
1
+ # Human Oversight Console Guide
2
+
3
+ AgentCorp provides first-class Human-in-the-Loop (HITL) oversight designed for developer speed. You can review and approve agent actions directly inside your terminal or through a real-time web dashboard.
4
+
5
+ ---
6
+
7
+ ## 1. How It Works: Sequence & State Diagrams
8
+
9
+ ![AgentCorp Human-in-the-Loop Coordination Flow](../images/coordination-flow.jpg)
10
+
11
+ ### A. Inter-Agent Coordination Sequence Diagram
12
+
13
+ This diagram shows how messages move between agents, how policies are evaluated, and when human oversight is triggered:
14
+
15
+ ```mermaid
16
+ sequenceDiagram
17
+ autonumber
18
+ actor Codex as Codex (Architect / Planner)
19
+ participant Stdio as Stdio Adapter
20
+ participant Daemon as Central Broker Daemon
21
+ participant Policy as Policy Engine
22
+ actor Human as Human Developer (Terminal / Web)
23
+ actor Gemini as Antigravity (Developer)
24
+
25
+ Note over Codex, Gemini: Case 1: Auto-Approved Message (e.g. read_only report)
26
+ Codex->>Stdio: send_message(to="developer", type="report", risk_tags=["read_only"])
27
+ Stdio->>Daemon: HTTP POST /mcp (Bearer Token: architect)
28
+ Daemon->>Policy: Evaluate policies for "report" + ["read_only"]
29
+ Policy-->>Daemon: MATCH: "allow-read-only-reports" -> action="auto_approve"
30
+ Daemon->>Daemon: Store in messages (status="delivered")
31
+ Daemon-->>Gemini: Delivered to Inbox (No human approval needed!)
32
+ Daemon-->>Stdio: { status: "delivered", messageId: "msg_..." }
33
+ Stdio-->>Codex: Success
34
+
35
+ Note over Codex, Gemini: Case 2: Human-Gated Message (e.g. proposal or task completion)
36
+ Codex->>Stdio: send_message(to="developer", type="proposal", payload={...})
37
+ Stdio->>Daemon: HTTP POST /mcp (Bearer Token: architect)
38
+ Daemon->>Policy: Evaluate policies for "proposal"
39
+ Policy-->>Daemon: MATCH: "gate-critical-proposals" -> action="require_human"
40
+ Daemon->>Daemon: Store in pending_approval (Recipient CANNOT see message)
41
+ Daemon-->>Stdio: { status: "held_for_approval", approvalId: "apr_..." }
42
+ Stdio-->>Codex: Queued for Human Sign-off
43
+
44
+ Note over Human, Daemon: Human Review Session (agentcorp review)
45
+ Human->>Daemon: agentcorp review (or web console)
46
+ Daemon-->>Human: Displays pending approval & payload preview
47
+ Human->>Daemon: Press [a] Approve (or [e] Edit & Approve, [r] Reject)
48
+ Daemon->>Daemon: Update approval (status="approved"), message (status="delivered")
49
+ Daemon->>Daemon: Activate linked task as assigned
50
+ Daemon-->>Gemini: Approved handoff appears in get_work_queue
51
+ Gemini->>Daemon: accept_handoff("msg_...")
52
+ Daemon->>Daemon: Acknowledge proposal and start task
53
+ ```
54
+
55
+ ---
56
+
57
+ ### B. Lifecycle State Diagrams
58
+
59
+ #### Message Lifecycle State Machine
60
+
61
+ ```mermaid
62
+ stateDiagram-v2
63
+ [*] --> Submitted: send_message()
64
+
65
+ state "Policy Evaluation" as Eval
66
+ Submitted --> Eval
67
+
68
+ Eval --> Delivered: Rule matches "auto_approve"<br/>(e.g. read_only reports)
69
+ Eval --> PendingApproval: Rule matches "require_human"<br/>or no rule matches (Safe default)
70
+
71
+ state "Human Decision (agentcorp review)" as Decision
72
+ PendingApproval --> Decision
73
+
74
+ Decision --> Delivered: Human [a]pproves or [e]dits
75
+ Decision --> Rejected: Human [r]ejects
76
+
77
+ Delivered --> Acknowledged: Recipient calls acknowledge_message()
78
+
79
+ Acknowledged --> [*]
80
+ Rejected --> [*]
81
+ ```
82
+
83
+ #### Task Lifecycle State Machine
84
+
85
+ ```mermaid
86
+ stateDiagram-v2
87
+ [*] --> proposed: create_task()
88
+ proposed --> assigned: Linked proposal approved
89
+ assigned --> in_progress: Agent calls accept_handoff
90
+ in_progress --> blocked: Agent encounters dependency
91
+ blocked --> in_progress: Dependency resolved
92
+
93
+ state "Policy Evaluation" as TaskPolicy
94
+ in_progress --> TaskPolicy: update_task_status("completed")
95
+
96
+ TaskPolicy --> PendingSignOff: "gate-task-completion" policy
97
+ PendingSignOff --> completed: Human verifies & signs off [a]
98
+ PendingSignOff --> in_progress: Human rejects completion [r]
99
+
100
+ in_progress --> cancelled: Task abandoned
101
+ completed --> [*]
102
+ cancelled --> [*]
103
+ ```
104
+
105
+ ---
106
+
107
+ ## 2. Terminal-Native Interaction (Preferred)
108
+
109
+ Terminal-native interaction provides instantaneous, zero-latency review without context switching into a browser.
110
+
111
+ ### A. Dashboard Overview (`agentcorp console`)
112
+ Run the console command to view system status, task counts, and pending approvals:
113
+
114
+ ```sh
115
+ agentcorp console
116
+ ```
117
+
118
+ Example output (the automatically selected port varies):
119
+ ```text
120
+ ┌─────────────────────────────────────────────────────────────┐
121
+ │ AGENTCORP :: Human Approval & Coordination Console │
122
+ └─────────────────────────────────────────────────────────────┘
123
+
124
+ Status Summary:
125
+ Pending Approvals: 1
126
+ Total Tasks: 3
127
+ Daemon URL: http://127.0.0.1:54321
128
+ Web Dashboard: http://127.0.0.1:54321/console
129
+
130
+ Pending Approvals Queue:
131
+ • apr_b12480ad-191a-45c1-92ee-48c68832a820 (message) by architect [2026-09-05T00:30:12.000Z]
132
+
133
+ Review pending approvals now? [Y/n]
134
+ ```
135
+
136
+ If pending items exist, pressing <kbd>Enter</kbd> or <kbd>Y</kbd> immediately launches the interactive review session.
137
+
138
+ ---
139
+
140
+ ### B. Interactive Review Loop (`agentcorp review`)
141
+ Run `agentcorp review` (or `agentcorp approvals review`) to step through pending requests one by one:
142
+
143
+ ```sh
144
+ agentcorp review
145
+ ```
146
+
147
+ For each item, you see:
148
+ - Approval ID and subject (`[MESSAGE]` or `[TASK TRANSITION]`).
149
+ - Requesting agent role and target recipient.
150
+ - Formatted context and JSON payload.
151
+
152
+ #### Keyboard Actions:
153
+ | Key | Action | Description |
154
+ |---|---|---|
155
+ | <kbd>a</kbd> | **Approve** | Signs off immediately. Prompts for an optional reviewer note. |
156
+ | <kbd>e</kbd> | **Edit & Approve** | Prompts for a revised JSON payload. Validates syntax in real time and delivers the modified message to the recipient. |
157
+ | <kbd>r</kbd> | **Reject** | Rejects the request. Prompts for feedback/reason that will be recorded in the audit trail. |
158
+ | <kbd>s</kbd> | **Skip** | Skips the current item without making a decision. |
159
+ | <kbd>q</kbd> | **Quit** | Exits the review session cleanly. |
160
+
161
+ ---
162
+
163
+ ## 2. Real-Time Web Dashboard (`agentcorp console --browser`)
164
+
165
+ If you prefer a visual interface, launch the dark glassmorphic web dashboard:
166
+
167
+ ```sh
168
+ agentcorp console --browser
169
+ ```
170
+
171
+ ### Dashboard Features:
172
+ 1. **Live SSE Indicator**: Pulsing connection badge powered by Server-Sent Events (`/api/events`). No polling required.
173
+ 2. **Approvals Feed**: Real-time sign-off feed with one-click **Approve**, **Reject**, or **Edit & Approve** with a side-by-side JSON diff editor.
174
+ 3. **Role Inboxes**: Inspect messages delivered to each agent's inbox, track read receipts, and view full threads.
175
+ 4. **Tasks Kanban**: Live tracking across `open`, `in_progress`, `blocked`, and `completed` states.
176
+ 5. **Artifacts Catalog**: Inspect SHA-256 addressed artifacts, metadata, and visibility boundaries.
177
+ 6. **Policy Manager**: View all runtime policies and toggle them on/off with instant switches.
@@ -0,0 +1,235 @@
1
+ # MCP Tools Reference
2
+
3
+ AgentCorp exposes 15 coordination tools over the Model Context Protocol (MCP). Every tool call executes within the authenticated role context of the connection, meaning caller identity (`fromRole`, `producedBy`, `callerRole`) is enforced server-side and cannot be spoofed.
4
+
5
+ ---
6
+
7
+ ## 1. Identity & Registration
8
+
9
+ ### `whoami`
10
+ Inspect the bound AgentCorp role and connection identity.
11
+
12
+ * **Inputs**: None (`{}`)
13
+ * **Returns**:
14
+ ```json
15
+ {
16
+ "role": {
17
+ "id": "developer",
18
+ "display_name": "Developer",
19
+ "model": "any/mcp-capable-agent",
20
+ "interface": "mcp",
21
+ "capabilities": ["write_code", "run_tests", "report"],
22
+ "allowed_peers": ["architect"],
23
+ "artifact_visibility": ["architect", "developer"]
24
+ },
25
+ "agentId": "developer-daemon",
26
+ "company": "My Agent Company"
27
+ }
28
+ ```
29
+
30
+ ### `register_role`
31
+ Optionally bind this role-scoped MCP connection to an agent instance with restricted capabilities. Capabilities may only be reduced, never escalated beyond `org.toml`.
32
+
33
+ * **Inputs**:
34
+ * `capabilities` *(array of strings, optional)*: Subscribed capability subset.
35
+ * **Returns**: Updated role definition record.
36
+
37
+ ---
38
+
39
+ ## 2. Task Management
40
+
41
+ ### `create_task`
42
+ Creates a new coordinated task in the broker.
43
+
44
+ * **Inputs**:
45
+ * `title` *(string, required)*: Brief summary of the task.
46
+ * `description` *(string, optional)*: Detailed task requirements, constraints, or acceptance criteria.
47
+ * `assigned_to` *(string, optional)*: Intended assignee role (must be an allowed peer). The task remains `proposed` and hidden from that role until a linked proposal is approved.
48
+ * **Returns**:
49
+ ```json
50
+ {
51
+ "taskId": "tsk_01h8x...",
52
+ "title": "Implement auth header hardening",
53
+ "description": "Enforce Bearer authorization headers and remove query params",
54
+ "createdBy": "architect",
55
+ "assignedTo": "developer",
56
+ "status": "proposed",
57
+ "createdAt": "2026-09-05T00:00:00.000Z",
58
+ "updatedAt": "2026-09-05T00:00:00.000Z"
59
+ }
60
+ ```
61
+
62
+ ### `list_tasks`
63
+ Lists visible tasks where the caller's role participates. A proposed task is not visible to its intended assignee until an approved proposal activates the assignment.
64
+
65
+ * **Inputs**:
66
+ * `limit` *(integer, optional)*: Maximum number of tasks to return (default: `50`, max: `200`).
67
+ * `cursor` *(string, optional)*: Cursor from a previous page's `nextCursor`.
68
+ * `envelope` *(boolean, optional)*: If `true`, returns `{ items: [...], nextCursor: string | null }`. If omitted or `false`, returns the array of tasks directly for backward compatibility.
69
+ * **Returns**: Array of `TaskRecord` objects (or paginated envelope if `envelope: true`).
70
+
71
+ ### `get_work_queue`
72
+ Returns the bound role's complete actionable coordination state in one call.
73
+
74
+ * **Inputs**: None (`{}`)
75
+ * **Returns**: Unread delivered messages, non-terminal visible tasks, summary counts, and prioritized `nextActions`. When an action can be performed directly, `suggestedTool` contains the exact MCP tool name and arguments.
76
+ * **Recommended use**: Call at session start and after every handoff or task-status change instead of separately reconciling the inbox, task list, and threads.
77
+
78
+ ### `update_task_status`
79
+ Transitions a task through its validated lifecycle state graph (`proposed` → `assigned` → `in_progress` → `blocked` / `awaiting_review` → `completed` / `failed` / `cancelled`).
80
+
81
+ * **Inputs**:
82
+ * `task_id` *(string, required)*: Task ID to transition.
83
+ * `new_status` *(string, required)*: Target status (`proposed`, `assigned`, `in_progress`, `blocked`, `awaiting_review`, `completed`, `failed`, `cancelled`).
84
+ * `risk_tags` *(array of strings, optional)*: Caller-declared risk tags (e.g. `["read_only"]`).
85
+ * **Returns**: Updated `TaskRecord`. If the transition is gated by policy (such as `gate-task-completion`), the transition enters `pending_approval` until approved by a human operator.
86
+
87
+ ---
88
+
89
+ ## 3. Inter-Agent Messaging
90
+
91
+ ### `send_message`
92
+ Submits a typed message through recipient validation and the policy engine.
93
+
94
+ * **Inputs**:
95
+ * `to_role` *(string, required)*: Recipient role ID (must be in sender's `allowed_peers`).
96
+ * `type` *(string, required)*: Message type:
97
+ * `"proposal"`: Formal plan or change proposal (**strictly held for human approval**).
98
+ * `"question"`: Inquiry to peer agent.
99
+ * `"answer"`: Response to inquiry.
100
+ * `"report"`: Structured execution report.
101
+ * `"review"`: Architectural or code review.
102
+ * `"verdict"`: Formal review verdict (`go`, `no_go`, `changes_requested`).
103
+ * `"status_update"`: Execution milestone update.
104
+ * `payload` *(unknown / JSON object, required)*: Structured message payload (maximum size: 1 MB by default; exceeds return `PAYLOAD_TOO_LARGE`).
105
+ * `task_id` *(string, optional)*: Associated task ID.
106
+ * `references` *(array of strings, optional)*: Referenced artifact IDs or URIs.
107
+ * `risk_tags` *(array of strings, optional)*: Tags indicating risk category (e.g. `["read_only"]`).
108
+ * `in_reply_to` *(string, optional)*: ID of the message being answered.
109
+ * **Returns**:
110
+ ```json
111
+ {
112
+ "messageId": "msg_9f2a...",
113
+ "taskId": "tsk_01h8x...",
114
+ "fromRole": "architect",
115
+ "toRole": "developer",
116
+ "type": "proposal",
117
+ "payload": { "spec": "0.1.0-alpha.1" },
118
+ "references": ["art_123..."],
119
+ "inReplyTo": null,
120
+ "status": "pending_approval",
121
+ "riskTags": ["read_only"],
122
+ "createdAt": "2026-09-05T00:00:00.000Z",
123
+ "resolvedAt": null
124
+ }
125
+ ```
126
+
127
+ ### `get_inbox`
128
+ Retrieves delivered and approved messages addressed to the bound role. Messages held in `pending_approval` are not visible to the recipient until approved.
129
+
130
+ * **Inputs**:
131
+ * `limit` *(integer, optional)*: Maximum number of messages to return (default: `50`, max: `200`).
132
+ * `cursor` *(string, optional)*: Cursor from a previous page's `nextCursor`.
133
+ * `envelope` *(boolean, optional)*: If `true`, returns `{ items: [...], nextCursor: string | null }`. If omitted or `false`, returns the array directly.
134
+ * **Returns**: Array of unread `MessageRecord` objects with `status: "delivered"` or `"approved"` (or envelope if requested). Acknowledged messages remain in task history but leave the inbox.
135
+
136
+ ### `acknowledge_message`
137
+ Marks a delivered message as acknowledged by its recipient.
138
+
139
+ * **Inputs**:
140
+ * `message_id` *(string, required)*: Message ID to acknowledge.
141
+ * **Returns**: Updated `MessageRecord` with `status: "acknowledged"`.
142
+
143
+ Acknowledgement is idempotent: retrying an already acknowledged message returns its current record.
144
+
145
+ ### `accept_handoff`
146
+ Accepts an approved task proposal using one idempotent coordination operation.
147
+
148
+ * **Inputs**:
149
+ * `message_id` *(string, required)*: Delivered proposal message linked to a task assigned to the caller.
150
+ * **Behavior**: Acknowledges the proposal and requests the linked task's `in_progress` transition. If that transition requires human approval, retries reuse the existing pending transition rather than creating duplicate approvals.
151
+ * **Returns**: The acknowledged message, current task, and `pendingApproval` flag.
152
+
153
+ ### `get_thread`
154
+ Retrieves the complete message history for a given task visible to the caller's role.
155
+
156
+ * **Inputs**:
157
+ * `task_id` *(string, required)*: Associated task ID.
158
+ * `limit` *(integer, optional)*: Maximum number of messages to return (default: `50`, max: `200`).
159
+ * `cursor` *(string, optional)*: Cursor from a previous page's `nextCursor`.
160
+ * `envelope` *(boolean, optional)*: If `true`, returns `{ items: [...], nextCursor: string | null }`. If omitted or `false`, returns the array directly.
161
+ * **Returns**: Ordered chronological array of `MessageRecord` objects (or envelope if requested).
162
+
163
+ ---
164
+
165
+ ## 4. Artifact Management
166
+
167
+ ### `create_artifact`
168
+ Publishes an immutable, SHA-256 content-addressed artifact with role-based visibility.
169
+
170
+ * **Inputs**:
171
+ * `type` *(string, required)*: Artifact type (`spec`, `review`, `resolution`, `code_diff`, `report`).
172
+ * `name` *(string, required)*: Human-readable display filename.
173
+ * `content` *(string, optional)*: Inline text content (maximum size: 5 MB by default; exceeds return `ARTIFACT_TOO_LARGE`).
174
+ * `content_uri` *(string, optional)*: External storage reference (e.g. `file://...` or `s3://...`).
175
+ * `visible_to_roles` *(array of strings or "all", optional)*: Permitted roles. Defaults to role's `artifact_visibility`.
176
+ * `related_task_id` *(string, optional)*: Task ID to associate with this artifact.
177
+ * **Returns**:
178
+ ```json
179
+ {
180
+ "artifactId": "art_800eb174...",
181
+ "type": "review",
182
+ "name": "agentcorp-architect-release-verdict.md",
183
+ "producedBy": "architect",
184
+ "contentHash": "977b4f5325a4c5885de41f...",
185
+ "visibleToRoles": ["architect", "developer"],
186
+ "relatedTaskId": "tsk_01h8x...",
187
+ "createdAt": "2026-09-05T00:00:00.000Z"
188
+ }
189
+ ```
190
+
191
+ ### `list_artifacts`
192
+ Lists artifact metadata visible to the caller's role. Content is omitted from list results for performance.
193
+
194
+ * **Inputs**:
195
+ * `task_id` *(string, optional)*: Filter by associated task ID.
196
+ * `limit` *(integer, optional)*: Maximum number of artifacts to return (default: `50`, max: `200`).
197
+ * `cursor` *(string, optional)*: Cursor from a previous page's `nextCursor`.
198
+ * `envelope` *(boolean, optional)*: If `true`, returns `{ items: [...], nextCursor: string | null }`. If omitted or `false`, returns the array directly.
199
+ * **Returns**: Array of `ArtifactRecord` metadata objects (or envelope if requested).
200
+
201
+ ### `get_artifact`
202
+ Fetches complete artifact content and metadata after verifying that the caller's role is in the artifact's allowed visibility list.
203
+
204
+ * **Inputs**:
205
+ * `artifact_id` *(string, required)*: Artifact ID to retrieve.
206
+ * **Returns**: Complete `ArtifactRecord` including `content` or `contentUri`.
207
+
208
+ ---
209
+
210
+ ## 5. Idempotency & Operation Lookup
211
+
212
+ ### `get_operation`
213
+ Look up a previously executed idempotent operation result by its idempotency key.
214
+
215
+ * **Inputs**:
216
+ * `idempotency_key` *(string, required)*: The idempotency key passed during operation execution.
217
+ * **Returns**:
218
+ ```json
219
+ {
220
+ "found": true,
221
+ "operation": {
222
+ "key": "create-task-001",
223
+ "roleId": "developer",
224
+ "operation": "createTask",
225
+ "requestHash": "a1b2c3...",
226
+ "responseJson": "{\"taskId\":\"task_...\"}",
227
+ "createdAt": "2026-09-05T00:00:00.000Z"
228
+ }
229
+ }
230
+ ```
231
+
232
+ > [!NOTE]
233
+ > All mutation tools (`create_task`, `send_message`, `accept_handoff`, `create_artifact`, `update_task_status`) accept an optional `idempotency_key` string.
234
+ > Replays with identical keys and request payloads return cached results atomically.
235
+ > Replaying a key with a mismatched operation or mismatched payload raises `IDEMPOTENCY_CONFLICT`.
@@ -0,0 +1,105 @@
1
+ # Policy & Safety Guide
2
+
3
+ AgentCorp is designed with a **safe-by-default** governance model. No agent action is auto-approved unless an explicit policy rule permits it.
4
+
5
+ ---
6
+
7
+ ## 1. How Policy Evaluation Works
8
+
9
+ When an agent requests an action (sending a message or transitioning a task), the broker evaluates active policies:
10
+
11
+ 1. **Descending Priority Order**: Rules with higher `priority` integer values are checked first.
12
+ 2. **First Match Wins**: The first policy whose criteria all match dictates the action (`auto_approve` or `require_human`).
13
+ 3. **Default Fallback**: If no active rule matches the request, AgentCorp requires human sign-off (`require_human`).
14
+
15
+ ---
16
+
17
+ ## 2. Policy Subjects & Match Criteria
18
+
19
+ ### Subject: `message`
20
+
21
+ Used to govern inter-agent communication:
22
+
23
+ | Field | Type | Description |
24
+ |---|---|---|
25
+ | `subject` | `"message"` | Identifies message governance. |
26
+ | `priority` | number | Order of evaluation (e.g. `100`, `50`). |
27
+ | `from_role` | string (optional) | Match only messages from this sender role. |
28
+ | `to_role` | string (optional) | Match only messages to this recipient role. |
29
+ | `message_type` | string (optional) | Match specific types (e.g. `proposal`, `report`, `diff`). |
30
+ | `risk_tags` | string[] (optional) | Subset matching: every tag listed in the policy must be declared on the message. |
31
+ | `action` | `"auto_approve"` \| `"require_human"` | The decision to apply. |
32
+
33
+ #### Example: Auto-Approve Read-Only Reports
34
+ ```toml
35
+ [[policies]]
36
+ id = "allow-read-only-reports"
37
+ subject = "message"
38
+ priority = 100
39
+ risk_tags = ["read_only"]
40
+ action = "auto_approve"
41
+ ```
42
+
43
+ #### Example: Gate Architecture Proposals
44
+ ```toml
45
+ [[policies]]
46
+ id = "gate-proposals"
47
+ subject = "message"
48
+ priority = 90
49
+ message_type = "proposal"
50
+ action = "require_human"
51
+ ```
52
+
53
+ ---
54
+
55
+ ### Subject: `task`
56
+
57
+ Used to govern task status lifecycle transitions:
58
+
59
+ | Field | Type | Description |
60
+ |---|---|---|
61
+ | `subject` | `"task"` | Identifies task transition governance. |
62
+ | `priority` | number | Order of evaluation. |
63
+ | `from_status` | string (optional) | Current status of the task. |
64
+ | `to_status` | string (optional) | Target status being transitioned into (`in_progress`, `completed`, etc.). |
65
+ | `action` | `"auto_approve"` \| `"require_human"` | The decision to apply. |
66
+
67
+ #### Example: Allow Starting Work
68
+ ```toml
69
+ [[policies]]
70
+ id = "allow-start-work"
71
+ subject = "task"
72
+ priority = 80
73
+ to_status = "in_progress"
74
+ action = "auto_approve"
75
+ ```
76
+
77
+ #### Example: Gate Task Completion
78
+ ```toml
79
+ [[policies]]
80
+ id = "gate-completion"
81
+ subject = "task"
82
+ priority = 100
83
+ to_status = "completed"
84
+ action = "require_human"
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 3. Runtime Policy Management
90
+
91
+ Policies are initially seeded into SQLite from `org.toml`. After the first run, policies can be dynamically modified at runtime without restarting the daemon:
92
+
93
+ ```sh
94
+ # List all active and disabled policies
95
+ agentcorp policies list
96
+
97
+ # Disable a policy temporarily
98
+ agentcorp policies disable gate-proposals
99
+
100
+ # Re-enable a policy
101
+ agentcorp policies enable gate-proposals
102
+
103
+ # Add a new runtime policy via JSON
104
+ agentcorp policies set '{"id":"allow-diffs","subject":"message","priority":70,"message_type":"diff","action":"auto_approve"}'
105
+ ```
@@ -0,0 +1,65 @@
1
+ [company]
2
+ name = "Example Agent Company"
3
+
4
+ [limits]
5
+ max_request_body_bytes = 2097152
6
+ max_message_payload_bytes = 1048576
7
+ max_artifact_bytes = 5242880
8
+ default_page_size = 50
9
+ max_page_size = 200
10
+ max_audit_payload_bytes = 65536
11
+
12
+ [[roles]]
13
+ id = "architect"
14
+ display_name = "Architect"
15
+ model = "openai/codex"
16
+ interface = "mcp"
17
+ capabilities = ["propose_plan", "review", "approve_merge"]
18
+ allowed_peers = ["developer"]
19
+ artifact_visibility = ["architect", "developer"]
20
+
21
+ [[roles]]
22
+ id = "developer"
23
+ display_name = "Developer"
24
+ model = "any/mcp-capable-agent"
25
+ interface = "mcp"
26
+ capabilities = ["write_code", "run_tests", "report"]
27
+ allowed_peers = ["architect"]
28
+ artifact_visibility = ["architect", "developer"]
29
+
30
+ [[policies]]
31
+ id = "gate-critical-proposals"
32
+ subject = "message"
33
+ message_type = "proposal"
34
+ priority = 200
35
+ action = "require_human"
36
+
37
+ [[policies]]
38
+ id = "allow-read-only-status-updates"
39
+ subject = "message"
40
+ message_type = "status_update"
41
+ priority = 100
42
+ risk_tags = ["read_only"]
43
+ action = "auto_approve"
44
+
45
+ [[policies]]
46
+ id = "allow-read-only-reports"
47
+ subject = "message"
48
+ message_type = "report"
49
+ priority = 100
50
+ risk_tags = ["read_only"]
51
+ action = "auto_approve"
52
+
53
+ [[policies]]
54
+ id = "allow-start-work"
55
+ subject = "task"
56
+ priority = 50
57
+ to_status = "in_progress"
58
+ action = "auto_approve"
59
+
60
+ [[policies]]
61
+ id = "gate-task-completion"
62
+ subject = "task"
63
+ priority = 100
64
+ to_status = "completed"
65
+ action = "require_human"
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "agentcorp-broker",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Local-first MCP coordination broker for teams of AI agents",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "author": "AgentCorp contributors",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Shash-J/AgentCorp.git"
11
+ },
12
+ "homepage": "https://github.com/Shash-J/AgentCorp#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/Shash-J/AgentCorp/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=22.13.0"
18
+ },
19
+ "bin": {
20
+ "agentcorp": "dist/cli.js"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "docs",
31
+ "!docs/images/**",
32
+ "!docs/design-spec.md",
33
+ "examples",
34
+ "README.md",
35
+ "CONTRIBUTING.md",
36
+ "SECURITY.md",
37
+ "LICENSE",
38
+ "CHANGELOG.md"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json && node -e \"require('node:fs').cpSync('src/console', 'dist/console', { recursive: true, force: true })\"",
42
+ "check": "tsc -p tsconfig.json --noEmit",
43
+ "test": "vitest run",
44
+ "test:watch": "vitest",
45
+ "prepublishOnly": "npm run check && npm test",
46
+ "prepack": "npm run build"
47
+ },
48
+ "keywords": [
49
+ "ai-agents",
50
+ "mcp",
51
+ "multi-agent",
52
+ "coordination",
53
+ "human-in-the-loop",
54
+ "sqlite"
55
+ ],
56
+ "dependencies": {
57
+ "@modelcontextprotocol/client": "^2.0.0",
58
+ "@modelcontextprotocol/server": "^2.0.0",
59
+ "commander": "^14.0.0",
60
+ "smol-toml": "^1.4.2",
61
+ "zod": "^4.1.5"
62
+ },
63
+ "devDependencies": {
64
+ "@types/node": "^24.3.0",
65
+ "typescript": "^7.0.2",
66
+ "vitest": "^3.2.4"
67
+ }
68
+ }