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.
- package/CHANGELOG.md +52 -0
- package/CONTRIBUTING.md +20 -0
- package/LICENSE +201 -0
- package/README.md +250 -0
- package/SECURITY.md +23 -0
- package/dist/audit.d.ts +25 -0
- package/dist/audit.js +203 -0
- package/dist/audit.js.map +1 -0
- package/dist/broker.d.ts +103 -0
- package/dist/broker.js +805 -0
- package/dist/broker.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +712 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +41 -0
- package/dist/config.js.map +1 -0
- package/dist/console/console.css +794 -0
- package/dist/console/console.js +802 -0
- package/dist/console/index.html +309 -0
- package/dist/credentials.d.ts +16 -0
- package/dist/credentials.js +72 -0
- package/dist/credentials.js.map +1 -0
- package/dist/database.d.ts +119 -0
- package/dist/database.js +1356 -0
- package/dist/database.js.map +1 -0
- package/dist/diagnostics.d.ts +44 -0
- package/dist/diagnostics.js +357 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.js +215 -0
- package/dist/mcp.js.map +1 -0
- package/dist/migrations.d.ts +13 -0
- package/dist/migrations.js +266 -0
- package/dist/migrations.js.map +1 -0
- package/dist/policy.d.ts +22 -0
- package/dist/policy.js +33 -0
- package/dist/policy.js.map +1 -0
- package/dist/server.d.ts +49 -0
- package/dist/server.js +529 -0
- package/dist/server.js.map +1 -0
- package/dist/stdio-adapter.d.ts +230 -0
- package/dist/stdio-adapter.js +406 -0
- package/dist/stdio-adapter.js.map +1 -0
- package/dist/tui.d.ts +26 -0
- package/dist/tui.js +291 -0
- package/dist/tui.js.map +1 -0
- package/dist/types.d.ts +355 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -0
- package/docs/ARCHITECTURE.md +119 -0
- package/docs/README.md +37 -0
- package/docs/RELEASING.md +228 -0
- package/docs/ROADMAP.md +112 -0
- package/docs/cli-reference.md +133 -0
- package/docs/dogfooding-report.md +83 -0
- package/docs/getting-started.md +228 -0
- package/docs/guides/antigravity-setup.md +84 -0
- package/docs/guides/claude-cursor-setup.md +76 -0
- package/docs/guides/codex-setup.md +75 -0
- package/docs/guides/human-console.md +177 -0
- package/docs/mcp-tools-reference.md +235 -0
- package/docs/policy-guide.md +105 -0
- package/examples/org.toml +65 -0
- 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
|
+

|
|
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
|
+
}
|