You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 34040c9
Browse filesBrowse the repository at this point in the historyBrowse files
Update claude-api skill: Managed Agents auto permission policy and ant beta:sessions connect (#1750)
Adds the third Managed Agents permission policy, `auto`, alongside
`always_allow` / `always_ask`: the three outcomes (runs, denied as
high-risk with an error tool result while the session keeps running,
pauses for approval when indeterminate), a config example, what the
evaluation trusts, and the "not a human checkpoint" warning. Documents
the `evaluated_permission` and `evaluation` fields on `agent.tool_use` /
`agent.mcp_tool_use`, and updates the client-pattern and multiagent
guides to gate on `evaluated_permission === 'ask'` rather than the
configured policy.
Adds `ant beta:sessions connect` to the CLI guide: terminal viewer
keybindings, the allow/deny prompt, and the `--web` local session viewer.
Fixes the deny example to use `deny_message` (the real field) instead of
`message`.
Claude-Session: https://claude.ai/code/session_01UkZpc4FqLFPLBJF2Zcuq3a
Co-authored-by: Claude <[email protected]>
Copy file name to clipboardExpand all lines: skills/claude-api/SKILL.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -412,6 +412,8 @@ Availability: `shared/platform-availability.md`. For agents on Bedrock / Vertex
412
412
413
413
**When the user asks "how do I write the client code for X":** reach for `shared/managed-agents-client-patterns.md` - covers lossless stream reconnect, `processed_at` queued/processed gate, interrupt, `tool_confirmation` round-trip, the correct idle/terminated break gate, post-idle status race, stream-first ordering, file-mount gotchas, etc. For credentials, lead with vault `environment_variable` credentials - the first-class mechanism; secrets are substituted at egress and never enter the sandbox (`shared/managed-agents-tools.md` -> Vaults). Keeping credentials host-side via custom tools is the fallback where vault credentials don't fit (e.g. self-hosted sandboxes).
414
414
415
+
**When the user asks about tool approvals, permission policies, or "auto mode"** (which tool calls need a human, letting the server evaluate calls, `evaluated_permission` / `evaluation` on tool-use events): read `shared/managed-agents-tools.md` § Permission Policies - `always_allow` / `always_ask` / `auto` and the three `auto` outcomes (runs, denied as high-risk, pauses when indeterminate). For attaching a terminal to a live session (`ant beta:sessions connect`): `shared/anthropic-cli.md`.
416
+
415
417
**When the user wants the agent to run on a schedule** (cron, "every night", "weekly report"): read `shared/managed-agents-scheduled-deployments.md` - deployments fire sessions autonomously on a cron cadence, with per-firing run records and lifecycle controls (pause/unpause/archive).
416
418
417
419
**When the agent's work fans out** (research across several sources, per-file or per-record work, "look into N things, then summarize") **or one loop would fill its context with reading:** read `shared/managed-agents-multiagent.md` and recommend a multiagent session - start with just `{"type": "self"}` in the roster so the agent can delegate to copies of itself, then move reading-heavy sub-tasks to a cheaper worker agent (e.g. Claude Haiku 4.5) referenced by ID.
Copy file name to clipboardExpand all lines: skills/claude-api/shared/anthropic-cli.md
+23Lines changed: 23 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -188,6 +188,29 @@ ant beta:sessions:events list --session-id "$SID" --transform 'content.0.text' -
188
188
ant beta:sessions:events stream --session-id "$SID"# live event stream
189
189
```
190
190
191
+
### Attach a terminal to a session (`ant beta:sessions connect`)
192
+
193
+
`ant beta:sessions connect <session-id>` attaches your terminal to an existing session: it loads the transcript, follows it live, and lets you step in - send a message, interrupt, or allow/deny a tool call that is waiting for approval. Ctrl+C detaches; the session keeps running, and reconnecting reloads the full history. Read-only if the session is `terminated` or archived.
194
+
195
+
```sh
196
+
ant beta:sessions connect sesn_011CZkZAtmR3yMPDzynEDxu7 # terminal view
197
+
ant beta:sessions connect sesn_011CZkZAtmR3yMPDzynEDxu7 --web # Console session viewer, served locally
198
+
```
199
+
200
+
| Key | Action |
201
+
|---|---|
202
+
| Enter | Send input as a `user.message` (Alt+Enter / Ctrl+J for a newline) |
203
+
| Esc | Interrupt the running agent (`user.interrupt`) |
| PgUp / PgDn | Scroll; scrolling up pauses following, End resumes |
206
+
| Ctrl+C (or Ctrl+D on empty input) | Detach |
207
+
208
+
When a call is waiting for approval (`always_ask`, or `auto` with no determination), the input line becomes **Allow tool call?** with **Yes** / **No** / **No, and tell the agent why** - the CLI sends `user.tool_confirmation`, with your typed reason as `deny_message`. In multiagent sessions the terminal view follows the primary thread only (which includes coordinator<->subagent messages).
209
+
210
+
`--web` serves the Console's session viewer from a local server on `127.0.0.1`, prints the URL, and opens the browser (`--no-browser` to skip). The URL works once, within two minutes (reloading that tab is fine; to open it elsewhere, run the command again). The page talks only to the local `ant` process, which makes the API calls, so credentials never leave the CLI; the server runs until Ctrl+C. Unlike the terminal view, the browser viewer follows every thread of a multiagent session.
211
+
212
+
Needs an interactive terminal (except `--web`) - for scripts use `ant beta:sessions:events stream` / `send`, below.
213
+
191
214
### Interactive session loop (stream-before-send)
192
215
193
216
`ant beta:sessions:events stream` only delivers events emitted *after* the stream opens - so open it **before** sending the kickoff to avoid missing early events. Use process substitution to hold the stream on a file descriptor, send, then read:
| Anthropic CLI |`https://platform.claude.com/docs/en/api/sdks/cli.md`| "Extract CLI install, authentication, command structure, and the beta:agents/environments/sessions commands" |
128
+
|`ant beta:sessions connect`|`https://platform.claude.com/docs/en/cli-sdks-libraries/cli/sessions-connect.md`| "Extract the interactive session viewer: keybindings, tool-call allow/deny prompt, `--web` local viewer and its URL/lifetime rules" |
128
129
| Authentication overview |`https://platform.claude.com/docs/en/manage-claude/authentication.md`| "Extract the credential options (API keys, interactive OAuth login, Workload Identity Federation) and when to use each" |
129
130
| WIF reference |`https://platform.claude.com/docs/en/manage-claude/wif-reference.md`| "Extract credential precedence order, the profile configuration file schema, and the configuration directory layout" |
Copy file name to clipboardExpand all lines: skills/claude-api/shared/managed-agents-client-patterns.md
+6-4Lines changed: 6 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -81,11 +81,11 @@ Reference: `interrupt.ts` - sends the interrupt the moment it sees `span.model_r
81
81
82
82
## 4. `tool_confirmation` round-trip
83
83
84
-
When the agent has `permission_policy: { type: 'always_ask' }`, any call to that tool fires an `agent.tool_use` event with`evaluated_permission === 'ask'` and the session goes idle waiting for a decision. Respond with `user.tool_confirmation`.
84
+
When a call evaluates to `ask` - the tool has `permission_policy: { type: 'always_ask' }`, or it has `{ type: 'auto' }` and the server reached no determination - the `agent.tool_use`/ `agent.mcp_tool_use`event carries`evaluated_permission === 'ask'` and the session goes idle waiting for a decision. Respond with `user.tool_confirmation`.
85
85
86
86
```ts
87
87
forawait (const event ofstream) {
88
-
if (event.type==='agent.tool_use'&&event.evaluated_permission==='ask') {
88
+
if ((event.type==='agent.tool_use'||event.type==='agent.mcp_tool_use')&&event.evaluated_permission==='ask') {
@@ -101,7 +101,9 @@ for await (const event of stream) {
101
101
Key points:
102
102
-`tool_use_id` is `event.id` (typically `sevt_...`), **not** a `toolu_...` ID.
103
103
-`result` is `'allow' | 'deny'`. Use `deny_message` to tell the model *why* you denied - it gets surfaced back to the agent.
104
-
- Multiple pending tools: respond once per `agent.tool_use` event with `evaluated_permission === 'ask'`.
104
+
- Multiple pending tools: respond once per `agent.tool_use` / `agent.mcp_tool_use` event with `evaluated_permission === 'ask'`.
105
+
- Gate on `evaluated_permission === 'ask'`, not on the policy you configured - it covers `always_ask` and `auto`-indeterminate alike. Calls the server **denies** under `auto` (`evaluated_permission === 'deny'`, `evaluation.evaluated_permission.reason_code === 'high_risk'`) never enter this flow: the agent gets an error tool result and the session keeps running; sending a confirmation for one is a 400.
106
+
- Log `event.evaluation` for audit (`type` + `reason_code`), and tolerate a `type` or `reason_code` you don't recognize - branch on known values, pass unknown ones through.
105
107
106
108
Reference: `tool-permissions.ts`.
107
109
@@ -123,7 +125,7 @@ for await (const event of stream) {
123
125
```
124
126
125
127
`stop_reason.type` values on `session.status_idle`:
126
-
-`requires_action` - agent is waiting on a client-side event (tool confirmation, custom tool result). Handle it, don't break. **Self-hosted exception:** if the session went `requires_action`-idle with no pending `agent.tool_use`(always_ask) or `agent.custom_tool_use` to answer, the worker failed the claimed work item (typically a memory-store mount error, logged only on the worker host). Don't `continue` forever on that - surface it, fix the host, and send `user.interrupt` to re-queue the work (`shared/managed-agents-self-hosted-sandboxes.md` § Memory stores -> Troubleshooting).
128
+
-`requires_action` - agent is waiting on a client-side event (tool confirmation, custom tool result). Handle it, don't break. **Self-hosted exception:** if the session went `requires_action`-idle with no pending `agent.tool_use`/ `agent.mcp_tool_use` (`ask`) or `agent.custom_tool_use` to answer, the worker failed the claimed work item (typically a memory-store mount error, logged only on the worker host). Don't `continue` forever on that - surface it, fix the host, and send `user.interrupt` to re-queue the work (`shared/managed-agents-self-hosted-sandboxes.md` § Memory stores -> Troubleshooting).
127
129
-`retries_exhausted` - terminal failure. Break, then check `sessions.retrieve()` for the error state.
128
130
-`end_turn` - normal completion.
129
131
-`budget_reached` - the session hit its spend cap and paused. Not terminal and not resumable by any event: change (typically raise) or remove the session's `budget` to resume, or treat it as done. A `session.usage` event with the final cost immediately precedes this idle. See `shared/managed-agents-core.md` § Session budgets.
|`user.interrupt`| Interrupt the agent while it's running |
13
-
|`user.tool_confirmation`| Approve/deny a tool call (when `always_ask` policy) |
13
+
|`user.tool_confirmation`| Approve/deny a tool call that paused for approval (`always_ask`, or `auto` when the server reached no determination) |
14
14
|`user.custom_tool_result`| Provide result for a custom tool call |
15
15
|`user.define_outcome`| Start a rubric-graded iterate loop - see `shared/managed-agents-outcomes.md`|
16
16
|`system.message`| Append privileged system-level context for this turn and every turn after it; see § Adding system context mid-session |
@@ -63,9 +63,9 @@ Event types use dot notation, grouped by namespace:
63
63
| --- | --- |
64
64
|`agent.message`| Agent text output |
65
65
|`agent.thinking`| Progress signal that the agent is thinking - it does **not** carry the thinking content |
66
-
|`agent.tool_use`| Agent used a built-in tool (`agent_toolset_20260401`) |
66
+
|`agent.tool_use`| Agent used a built-in tool (`agent_toolset_20260401`). Carries `evaluated_permission` (`allow`/`ask`/`deny`) and usually `evaluation` - see `shared/managed-agents-tools.md` § `evaluated_permission` and `evaluation`|
67
67
|`agent.tool_result`| Result from a built-in tool |
68
-
|`agent.mcp_tool_use`| Agent used an MCP tool |
68
+
|`agent.mcp_tool_use`| Agent used an MCP tool. Carries `evaluated_permission` and usually `evaluation`, same as `agent.tool_use`|
69
69
|`agent.mcp_tool_result`| Result from an MCP tool |
70
70
|`agent.custom_tool_use`| Agent invoked a custom tool - session goes idle, you respond with `user.custom_tool_result`|
71
71
|`agent.thread_context_compacted`| Conversation context was compacted |
**Step 2 - move the reading-heavy work to a cheaper model.** Delegated research work is mostly searching, reading, and extracting: many input tokens, little hard reasoning. Create a second agent on a smaller model with a narrow `system` prompt and only the tools it needs, and list it next to `self`. A roster entry is only a reference: the worker runs on its own `model`, `system`, and `tools`, and its tokens are billed at its own model's rates. The large model spends its tokens on planning, checking, and synthesis; the small model does the bulk reading.
28
+
**Step 2 - move the reading-heavy work to a cheaper model.** Delegated research work is mostly searching, reading, and extracting: many input tokens, little hard reasoning. Create a second agent on a smaller current-generation model (Claude Haiku 4.5, or Claude Sonnet 5 when the worker needs more judgment) with a narrow `system` prompt and only the tools it needs, and list it next to `self`. A roster entry is only a reference: the worker runs on its own `model`, `system`, and `tools`, and its tokens are billed at its own model's rates. The large model spends its tokens on planning, checking, and synthesis; the small model does the bulk reading.
29
29
30
30
```python
31
31
worker = client.beta.agents.create(
@@ -222,7 +222,7 @@ No `agent.tool_use` and no `agent.thread_message_sent` are emitted for a consult
222
222
223
223
## Tool permissions and custom tools from subagent threads
224
224
225
-
When a subagent needs your client (an `always_ask` confirmation, or a custom tool result), the request is **cross-posted to the primary thread** with `session_thread_id` identifying the originating thread - so you only need to watch the session stream. Reply with `user.tool_confirmation` (carrying `tool_use_id`) or `user.custom_tool_result` (carrying `custom_tool_use_id`), and **echo the `session_thread_id` from the originating event** (the SDK param type and docstring expect it). The server also routes by the tool-use ID, so the echo is belt-and-suspenders rather than load-bearing - but include it.
225
+
When a subagent needs your client (a tool call that paused for approval - `always_ask`, or `auto` with no determination - or a custom tool result), the request is **cross-posted to the primary thread** with `session_thread_id` identifying the originating thread - so you only need to watch the session stream. Reply with `user.tool_confirmation` (carrying `tool_use_id`) or `user.custom_tool_result` (carrying `custom_tool_use_id`), and **echo the `session_thread_id` from the originating event** (the SDK param type and docstring expect it). The server also routes by the tool-use ID, so the echo is belt-and-suspenders rather than load-bearing - but include it.
226
226
227
227
```python
228
228
for event_id in stop.event_ids:
@@ -239,6 +239,8 @@ for event_id in stop.event_ids:
239
239
240
240
The same pattern applies to `user.custom_tool_result`.
241
241
242
+
**`auto` in multiagent sessions.** Only your `user.message` events on the primary thread can lead the server to allow a call it would otherwise deny under `auto`; nothing in a subagent's thread carries that weight (your client posts no messages there, and the coordinator's messages to the subagent carry none). A call the server denies under `auto` is **not** cross-posted - its event and the error tool result appear only on the subagent's own thread stream, and the subagent keeps running.
0 commit comments