mirror of
https://github.com/anthropics/skills.git
synced 2026-08-02 13:05:28 +08:00
Update claude-api skill: Managed Agents July launch wave, partner pricing, tool-runner corrections (#1463)
Syncs the claude-api skill with the current upstream source.
## Managed Agents — five new features
- `effort` on the agent's `model` object (a level string or `{"type": "<level>"}`).
It is agent-configuration only: setting it in a per-session `model` override is
silently ignored.
- Optional `version` on agent update, for optimistic concurrency. Omit it for
last-write-wins.
- `initial_events` on session create, collapsing create plus first send into one
call. Validation is all-or-nothing and only `user.message` and
`user.define_outcome` are accepted.
- Environment and memory-store webhooks: four `environment.*` events and three
`memory_store.*` events.
- Event deltas on per-thread streams. Previews are thread-scoped, so a child
thread's previews never reach the session-level stream.
## Corrections to behavior the skill already documented
- Tool output offload triggers at 100,000 characters (~25k tokens), not 100K
tokens, and covers built-in tools rather than MCP alone.
- `system.message` works on four models, checks only the primary model, appends
system context instead of replacing the prompt, and is accepted during a
`requires_action` idle when it trails a tool result in the same request.
- Vault-to-MCP credential matching is normalized (scheme and host lowercased,
default ports and trailing slashes stripped), not byte-exact.
- Multiagent depth greater than 1 is a validation error, not silently ignored.
- Outcome `interrupted` fires even when evaluation never started, and then
carries an empty-string `outcome_evaluation_start_id`.
- Deployment jitter is 15% of the run interval, floor 5s, cap 9 minutes.
- Webhooks retry three times with jittered 5-120s backoff, then drop silently.
Auto-disable is duration-based with three named triggers.
- `session.status_terminated` means completion or error.
- `agent.thinking` is a progress signal and carries no thinking content.
- `processed_at` is already populated on first sighting for
`user.define_outcome`, `user.custom_tool_result`, and `user.tool_result`.
- Session creation does not provision the sandbox.
- Skill `version` applies to Anthropic-authored skills too.
- Console-created vault credentials are header-injection only, and vault
environment-variable substitution skips secrets in URL paths.
- Console trace URLs need the real workspace ID when the API key is not in the
Default workspace.
## Elsewhere in the skill
- Note partner pricing under the first-party price table: Microsoft Foundry
bills at standard API rates, while Amazon Bedrock and Vertex AI are
partner-operated with separate pricing.
- Correct the tool-runner human-in-the-loop guidance, which previously pointed
readers at the manual loop for approval gates the runner's per-turn hooks
already cover.
- Repoint links away from the retired documentation hosts.
- Dedupe eagerly loaded SKILL.md content that the per-section files already
cover.
This commit is contained in:
@@ -13,14 +13,14 @@ Console → **Manage → Webhooks**. There is no programmatic endpoint-managemen
|
||||
| Field | Constraint |
|
||||
|---|---|
|
||||
| URL | HTTPS on port 443, publicly resolvable hostname |
|
||||
| Event types | Subscribe per `data.type` — you only receive subscribed types (plus test events) |
|
||||
| Event types | Subscribe per `data.type` — an endpoint receives only the types it is subscribed to |
|
||||
| Signing secret | `whsec_`-prefixed, 32 bytes, **shown once at creation** — store it |
|
||||
|
||||
---
|
||||
|
||||
## Verify the signature
|
||||
|
||||
Every delivery is HMAC-signed. **Use the SDK's `client.beta.webhooks.unwrap()`** — it verifies the signature, rejects payloads more than ~5 minutes old, and returns the parsed event. It reads the `whsec_` secret from `ANTHROPIC_WEBHOOK_SIGNING_KEY`.
|
||||
Every delivery carries the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers. **Use the SDK's `client.beta.webhooks.unwrap()`** — it verifies the signature, rejects payloads more than ~5 minutes old, and returns the parsed event. It reads the `whsec_` secret from `ANTHROPIC_WEBHOOK_SIGNING_KEY`. Pass the headers through untouched; don't hand-roll verification against a single `X-Webhook-Signature` header, which is not the wire format.
|
||||
|
||||
```python
|
||||
import anthropic
|
||||
@@ -63,7 +63,7 @@ Pass the **raw request body** to `unwrap()` — frameworks that re-serialize JSO
|
||||
```json
|
||||
{
|
||||
"type": "event",
|
||||
"id": "event_01ABC...",
|
||||
"id": "whe_9d5c1f7e...",
|
||||
"created_at": "2026-03-18T14:05:22Z",
|
||||
"data": {
|
||||
"type": "session.status_idled",
|
||||
@@ -74,7 +74,9 @@ Pass the **raw request body** to `unwrap()` — frameworks that re-serialize JSO
|
||||
}
|
||||
```
|
||||
|
||||
Switch on `data.type`, fetch the resource by `data.id`, return any **2xx** to acknowledge. `created_at` is when the *state transition* happened, not when the webhook fired.
|
||||
Switch on `data.type`, fetch the resource by `data.id`, return any **2xx** to acknowledge. `created_at` is when the *event occurred*, not when the delivery was attempted — the `webhook-timestamp` header is the clock for the attempt (see Delivery behavior).
|
||||
|
||||
The top-level `id` is the same value as the `webhook-id` header, and it is per *event*, not per delivery — every retry carries it unchanged. Dedupe on it.
|
||||
|
||||
---
|
||||
|
||||
@@ -85,16 +87,20 @@ Switch on `data.type`, fetch the resource by `data.id`, return any **2xx** to ac
|
||||
| `session.status_scheduled` | Session created and ready to accept events |
|
||||
| `session.status_run_started` | Agent execution kicked off (every transition to `running`) |
|
||||
| `session.status_idled` | Agent awaiting input (tool approval, custom tool result, or next message) |
|
||||
| `session.status_terminated` | Session hit a terminal error |
|
||||
| `session.status_rescheduled` | A transient error occurred; the session is retrying automatically |
|
||||
| `session.status_terminated` | Session ended — **on completion or on error**, not error-only |
|
||||
| `session.thread_created` | Multiagent: coordinator opened a new subagent thread |
|
||||
| `session.thread_idled` | Multiagent: a subagent thread is waiting for input |
|
||||
| `session.thread_terminated` | A thread ended — child completed its work, or the thread was archived. **Child threads only**; the primary thread's end surfaces as `session.status_terminated` |
|
||||
| `session.outcome_evaluation_ended` | Outcome grader finished one iteration |
|
||||
| `session.updated` | Session properties changed (name, configuration) |
|
||||
| `session.deleted` | Session permanently deleted — no object left to fetch; treat the event itself as final |
|
||||
| `vault.archived` | Vault was archived |
|
||||
| `vault.created` | Vault was created |
|
||||
| `vault.deleted` | Vault was deleted |
|
||||
| `vault_credential.archived` | Vault credential was archived |
|
||||
| `vault.deleted` | Vault was deleted — a `vault_credential.deleted` also fires per underlying credential. No object left to fetch; treat the event itself as final |
|
||||
| `vault_credential.archived` | Credential archived, directly or via vault archival |
|
||||
| `vault_credential.created` | Vault credential was created |
|
||||
| `vault_credential.deleted` | Vault credential was deleted |
|
||||
| `vault_credential.deleted` | Credential deleted, directly or via vault deletion. No object left to fetch; treat the event itself as final |
|
||||
| `vault_credential.refresh_failed` | MCP OAuth vault credential failed to refresh |
|
||||
| `agent.created` | Agent created |
|
||||
| `agent.updated` | A new agent version was published. Updates that do not create a new version do **not** fire this. |
|
||||
@@ -109,6 +115,15 @@ Switch on `data.type`, fetch the resource by `data.id`, return any **2xx** to ac
|
||||
| `deployment_run.started` | A **scheduled** run started. Manual runs do **not** emit `deployment_run.*` events. |
|
||||
| `deployment_run.succeeded` | Scheduled run created its session. Same `data.id` (the run ID) as the run's `.started` event — fetch the deployment run for its `session_id`, then subscribe to the session events to follow the work. |
|
||||
| `deployment_run.failed` | Scheduled run did not create a session. Same `data.id` as the run's `.started` event — fetch the deployment run for `error.type` / `error.message`. |
|
||||
| `environment.created` | Environment created |
|
||||
| `environment.updated` | Environment updated with at least one changed field. A no-op update emits nothing. |
|
||||
| `environment.archived` | Environment archived. Re-archiving an already-archived environment emits nothing. |
|
||||
| `environment.deleted` | Environment deleted, including delete of an already-archived one. No object left to fetch; treat the event itself as final |
|
||||
| `memory_store.created` | Memory store created — by you, or by an Anthropic-operated process that clones one of your stores |
|
||||
| `memory_store.archived` | Memory store archived. Re-archiving an already-archived store emits nothing. |
|
||||
| `memory_store.deleted` | Memory store deleted, including delete of an already-archived one. Cascades to its memories and versions **without** per-memory events — this single event is the signal. No object left to fetch; treat it as final |
|
||||
|
||||
> **There is deliberately no `memory_store.updated`.** Individual memories and memory versions emit no webhook events at all, and neither do an environment's self-hosted work items. If you need per-memory change tracking, poll the memory-versions endpoints (`shared/managed-agents-memory.md`).
|
||||
|
||||
> These are **webhook** `data.type` values — a separate namespace from SSE event types (`session.status_idle`, `span.outcome_evaluation_end`, etc. in `shared/managed-agents-events.md`). Don't reuse SSE constants in webhook handlers.
|
||||
|
||||
@@ -116,8 +131,13 @@ Switch on `data.type`, fetch the resource by `data.id`, return any **2xx** to ac
|
||||
|
||||
## Delivery behavior & pitfalls
|
||||
|
||||
- **No ordering guarantee.** `session.status_idled` may arrive before `session.outcome_evaluation_ended` even if the evaluation finished first. Sort by envelope `created_at` if order matters.
|
||||
- **Retries carry the same `event.id`.** At least one retry on non-2xx. Dedupe on `event.id`.
|
||||
- **3xx is failure.** Redirects are not followed — update the URL in Console if your endpoint moves.
|
||||
- **Auto-disable** after ~20 consecutive failed deliveries, or immediately if the hostname resolves to a private IP or returns a redirect. Re-enable manually in Console.
|
||||
- **Duplicates.** An endpoint can receive the same event more than once; every attempt carries the same top-level `event.id` (= the `webhook-id` header). Dedupe on it.
|
||||
- **Subscription scope.** An event reaches only endpoints subscribed to its type **at the moment it is emitted**. An event emitted while nothing was subscribed is never delivered, and subscribing later does not backfill — subscribe before you need the type.
|
||||
- **No ordering guarantee.** Events are not delivered in occurrence order: `session.status_idled` may arrive before `session.outcome_evaluation_ended`, and a `.deleted` can arrive before the `.archived` for the same resource. **Drive state from the resource you fetch, not from arrival order.**
|
||||
- **Retries: up to three attempts** per endpoint per event, with jittered exponential backoff between 5 and 120 seconds. A response that triggers auto-disable is never retried. **After the last attempt fails the event is dropped** — not queued, and with no signal that it was lost. Webhooks are not a durable log: if you must observe every transition, reconcile by listing or fetching the resource.
|
||||
- **`webhook-timestamp` is re-stamped on every attempt**, so retries don't fail the SDK's five-minute freshness check. It times the *delivery attempt*; use the payload's `created_at` for when the event occurred.
|
||||
- **Auto-disable — three triggers**, each setting `disabled_reason`, all reversible from Console (events emitted while disabled are **not** replayed):
|
||||
- A `3xx` response. Redirects are never followed; disables immediately, on the first attempt. Reason: `auto-disabled: endpoint URL returned a redirect (3xx)`.
|
||||
- The URL resolves to a non-public IP at connect time. Disables immediately. Reason: `auto-disabled: endpoint URL resolved to an invalid address`.
|
||||
- Continuous failure for a sustained period. Reason: `auto-disabled after sustained delivery failures`. **The trigger is duration, not a delivery count** — a single `2xx` resets the window, so one flaky event can't disable the endpoint.
|
||||
- **Thin payload is intentional.** Don't expect `stop_reason`, `outcome_evaluations`, credential secrets, etc. on the webhook body — fetch the resource.
|
||||
|
||||
Reference in New Issue
Block a user