mirror of
https://github.com/anthropics/skills.git
synced 2026-08-02 13:05:28 +08:00
1f630fdf92
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.
200 lines
9.8 KiB
Markdown
200 lines
9.8 KiB
Markdown
# Managed Agents — Memory Stores
|
|
|
|
> **Public beta.** Memory stores ship under the `managed-agents-2026-04-01` beta header; the SDK sets it automatically on all `client.beta.memory_stores.*` calls. If `client.beta.memory_stores` is missing, upgrade to the latest SDK release.
|
|
|
|
Sessions are ephemeral by default — when one ends, anything the agent learned is gone. A **memory store** is a workspace-scoped collection of small text documents that persists across sessions. When a store is attached to a session (via `resources[]`), it is mounted into the container as a filesystem directory; the agent reads and writes it with the ordinary file tools, and a system-prompt note tells it the mount is there.
|
|
|
|
Every mutation to a memory produces an immutable **memory version** (`memver_...`), giving you an audit trail and point-in-time rollback/redact.
|
|
|
|
> ⚠️ **Never store credentials, API keys, or tokens in memory stores.** Memories persist across sessions and are returned verbatim into future contexts — a key written once is replayed into every later session that mounts the store. Use vault `environment_variable` credentials instead (`shared/managed-agents-tools.md` → Vaults). If a secret has already been written, delete the memory and redact the affected versions (see "Redact a version" below).
|
|
|
|
## Object model
|
|
|
|
| Object | ID prefix | Scope | Notes |
|
|
| --- | --- | --- | --- |
|
|
| Memory store | `memstore_...` | Workspace | Attach to sessions via `resources[]` |
|
|
| Memory | `mem_...` | Store | One text file, addressed by `path` (≤ 100KB each — prefer many small files) |
|
|
| Memory version | `memver_...` | Memory | Immutable snapshot per mutation; `operation` ∈ `created` / `modified` / `deleted` |
|
|
|
|
## Create a store
|
|
|
|
`description` is passed to the agent so it knows what the store contains — write it for the model, not for humans.
|
|
|
|
```python
|
|
store = client.beta.memory_stores.create(
|
|
name="User Preferences",
|
|
description="Per-user preferences and project context.",
|
|
)
|
|
print(store.id) # memstore_01Hx...
|
|
```
|
|
|
|
Other SDKs: TypeScript `client.beta.memoryStores.create({...})`; Go `client.Beta.MemoryStores.New(ctx, ...)`. See `shared/managed-agents-api-reference.md` → SDK Method Reference for the full per-language table.
|
|
|
|
Stores support `retrieve` / `update` / `list` (with `include_archived`, `created_at_{gte,lte}` filters) / `delete` / **`archive`**. Archive makes the store read-only — existing session attachments continue, new sessions cannot reference it; no unarchive.
|
|
|
|
### Seed with content (optional)
|
|
|
|
Pre-load reference material before any session runs. `memories.create` creates a memory at the given `path`; if a memory already exists there the call returns `409` (`memory_path_conflict_error`, with the `conflicting_memory_id`). The store ID is the first positional argument.
|
|
|
|
```python
|
|
client.beta.memory_stores.memories.create(
|
|
store.id,
|
|
path="/formatting_standards.md",
|
|
content="All reports use GAAP formatting. Dates are ISO-8601...",
|
|
)
|
|
```
|
|
|
|
## Attach to a session
|
|
|
|
Memory stores go in the session's `resources[]` array alongside `file` and `github_repository` resources (see `shared/managed-agents-environments.md` → Resources). Memory stores attach at **session create time only** — `sessions.resources.add()` does not accept `memory_store`.
|
|
|
|
```python
|
|
session = client.beta.sessions.create(
|
|
agent=agent.id,
|
|
environment_id=environment.id,
|
|
resources=[
|
|
{
|
|
"type": "memory_store",
|
|
"memory_store_id": store.id,
|
|
"access": "read_write", # or "read_only"; default is "read_write"
|
|
"instructions": "User preferences and project context. Check before starting any task.",
|
|
}
|
|
],
|
|
)
|
|
```
|
|
|
|
| Field | Required | Notes |
|
|
| --- | --- | --- |
|
|
| `type` | ✅ | `"memory_store"` |
|
|
| `memory_store_id` | ✅ | `memstore_...` |
|
|
| `access` | — | `"read_write"` (default) or `"read_only"` — enforced at the filesystem level on the mount |
|
|
| `instructions` | — | Session-specific guidance for this store, in addition to the store's `name`/`description`. ≤ 4,096 chars. |
|
|
|
|
**Max 8 memory stores per session.** Attach multiple when different slices of memory have different owners or lifecycles — e.g. one read-only shared-reference store plus one read-write per-user store, or one store per end-user/team/project sharing a single agent config.
|
|
|
|
### How the agent sees it (FUSE mount)
|
|
|
|
Each attached store is mounted in the session container at `/mnt/memory/<store-name>/`. The agent interacts with it using the standard file tools (`bash`, `read`, `write`, `edit`, `glob`, `grep`) — there are no dedicated memory tools. `access: "read_only"` makes the mount read-only at the filesystem level; `"read_write"` allows the agent to create, edit, and delete files under it. A short description of each mount (name, path, `instructions`, access) is automatically injected into the system prompt so the agent knows the store exists without you having to mention it.
|
|
|
|
Writes the agent makes under the mount are persisted back to the store and produce memory versions just like host-side `memories.update` calls.
|
|
|
|
## Manage memories directly (host-side)
|
|
|
|
Use these for review workflows, correcting bad memories, or seeding stores out-of-band.
|
|
|
|
### List
|
|
|
|
Returns `Memory | MemoryPrefix` entries — a `MemoryPrefix` (`type: "memory_prefix"`, just a `path`) is a directory-like node when listing hierarchically. Use `path_prefix` to scope (include a trailing slash: `"/notes/"` matches `/notes/a.md` but not `/notes_backup/old.md`) and `depth` to bound the tree walk. `order_by` / `order` sort the result. Pass `view="full"` to include `content` in each item; the default `"basic"` returns metadata only.
|
|
|
|
```python
|
|
for m in client.beta.memory_stores.memories.list(store.id, path_prefix="/"):
|
|
if m.type == "memory":
|
|
print(f"{m.path} ({m.content_size_bytes} bytes, sha={m.content_sha256[:8]})")
|
|
else: # "memory_prefix"
|
|
print(f"{m.path}/")
|
|
```
|
|
|
|
### Read
|
|
|
|
```python
|
|
mem = client.beta.memory_stores.memories.retrieve(memory_id, memory_store_id=store.id)
|
|
print(mem.content)
|
|
```
|
|
|
|
`retrieve` defaults to `view="full"` (content included); `view` matters mainly on list endpoints.
|
|
|
|
### Create vs. update
|
|
|
|
| Operation | Addressed by | Semantics |
|
|
| --- | --- | --- |
|
|
| `memories.create(store_id, path=..., content=...)` | **Path** | Create at `path`. `409` (`memory_path_conflict_error`, includes `conflicting_memory_id`) if the path is already occupied. |
|
|
| `memories.update(mem_id, memory_store_id=..., path=..., content=...)` | **`mem_...` ID** | Mutate existing memory. Change `content`, `path` (rename), or both. Renaming onto an occupied path returns the same `409 memory_path_conflict_error`. |
|
|
|
|
```python
|
|
mem = client.beta.memory_stores.memories.create(
|
|
store.id,
|
|
path="/preferences/formatting.md",
|
|
content="Always use tabs, not spaces.",
|
|
)
|
|
|
|
client.beta.memory_stores.memories.update(
|
|
mem.id,
|
|
memory_store_id=store.id,
|
|
path="/archive/2026_q1_formatting.md", # rename
|
|
)
|
|
```
|
|
|
|
### Optimistic concurrency (precondition on `update`)
|
|
|
|
`memories.update` accepts a `precondition` so you can read → modify → write back without clobbering a concurrent writer. The only supported type is `content_sha256`. On mismatch the API returns `409` (`memory_precondition_failed_error`) — re-read and retry against fresh state.
|
|
|
|
```python
|
|
client.beta.memory_stores.memories.update(
|
|
mem.id,
|
|
memory_store_id=store.id,
|
|
content="CORRECTED: Always use 2-space indentation.",
|
|
precondition={"type": "content_sha256", "content_sha256": mem.content_sha256},
|
|
)
|
|
```
|
|
|
|
### Delete
|
|
|
|
```python
|
|
client.beta.memory_stores.memories.delete(mem.id, memory_store_id=store.id)
|
|
```
|
|
|
|
Pass `expected_content_sha256` for a conditional delete.
|
|
|
|
## Audit and rollback — memory versions
|
|
|
|
Every mutation creates an immutable `memver_...` snapshot. Versions accumulate for the lifetime of the parent memory; `memories.retrieve` always returns the current head, the version endpoints give you history.
|
|
|
|
| Operation that triggers it | `operation` field on the version |
|
|
| --- | --- |
|
|
| `memories.create` at a new path | `"created"` |
|
|
| `memories.update` changing `content`, `path`, or both (or an agent-side write to the mount) | `"modified"` |
|
|
| `memories.delete` | `"deleted"` |
|
|
|
|
Each version also records `created_by` — an actor object with `type` ∈ `session_actor` / `api_actor` / `user_actor` — and, after redaction, `redacted_at` + `redacted_by`.
|
|
|
|
### List versions
|
|
|
|
Newest-first, paginated. Filter by `memory_id`, `operation`, `session_id`, `api_key_id`, or `created_at_gte` / `created_at_lte`. Pass `view="full"` to include `content`; default is metadata-only.
|
|
|
|
```python
|
|
for v in client.beta.memory_stores.memory_versions.list(store.id, memory_id=mem.id):
|
|
print(f"{v.id}: {v.operation}")
|
|
```
|
|
|
|
### Retrieve a version
|
|
|
|
```python
|
|
version = client.beta.memory_stores.memory_versions.retrieve(
|
|
version_id, memory_store_id=store.id
|
|
)
|
|
print(version.content)
|
|
```
|
|
|
|
### Redact a version
|
|
|
|
Scrubs content from a historical version while preserving the audit trail (actor + timestamps). Clears `content`, `content_sha256`, `content_size_bytes`, and `path`; everything else stays. Use for leaked secrets, PII, or user-deletion requests.
|
|
|
|
```python
|
|
client.beta.memory_stores.memory_versions.redact(version_id, memory_store_id=store.id)
|
|
```
|
|
|
|
## Endpoint reference
|
|
|
|
See `shared/managed-agents-api-reference.md` → Memory Stores / Memories / Memory Versions for the full HTTP method/path tables. Raw HTTP base path:
|
|
|
|
```
|
|
POST /v1/memory_stores
|
|
POST /v1/memory_stores/{memory_store_id}/archive
|
|
GET /v1/memory_stores/{memory_store_id}/memories
|
|
PATCH /v1/memory_stores/{memory_store_id}/memories/{memory_id}
|
|
GET /v1/memory_stores/{memory_store_id}/memory_versions
|
|
POST /v1/memory_stores/{memory_store_id}/memory_versions/{version_id}/redact
|
|
```
|
|
|
|
For cURL examples and the CLI (`ant beta:memory-stores ...`), WebFetch the Memory URL in `shared/live-sources.md` → Managed Agents.
|