@preapexis/piexis 0.2.2 → 0.2.4

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 (149) hide show
  1. package/AGENTS.md +21 -41
  2. package/README.md +73 -139
  3. package/extensions/agents.ts +205 -0
  4. package/extensions/ask-question.ts +54 -95
  5. package/extensions/recommended-tools.ts +62 -0
  6. package/extensions/ui.ts +204 -58
  7. package/lib/agent-config.ts +55 -0
  8. package/lib/agents.ts +208 -0
  9. package/lib/question-model.ts +98 -0
  10. package/lib/question-ui.ts +214 -0
  11. package/lib/recommended-tools.ts +119 -0
  12. package/lib/subagent-runner.ts +146 -0
  13. package/lib/ui-tips.json +41 -0
  14. package/package.json +5 -13
  15. package/prompts/init.md +10 -2
  16. package/prompts/summary.md +7 -6
  17. package/schemas/agent.schema.json +48 -0
  18. package/skills/{claude-api/LICENSE.txt → caveman/LICENSE} +2 -2
  19. package/skills/caveman/LICENSE-MIT +21 -0
  20. package/skills/caveman/NOTICE +10 -0
  21. package/skills/caveman/SKILL.md +89 -0
  22. package/skills/find-skills/SKILL.md +141 -0
  23. package/skills/ponytail/LICENSE +21 -0
  24. package/skills/ponytail/NOTICE +9 -0
  25. package/skills/ponytail/SKILL.md +52 -0
  26. package/skills-lock.json +6 -0
  27. package/tests/agents.test.mjs +605 -0
  28. package/tests/ask-question-pty.test.mjs +16 -0
  29. package/tests/ask-question.test.mjs +269 -0
  30. package/tests/fixtures/agents-provider.ts +55 -0
  31. package/tests/fixtures/ask-question-pty.py +91 -0
  32. package/tests/fixtures/ask-question-terminal.mjs +69 -0
  33. package/tests/fixtures/recommended-tools-terminal.mjs +103 -0
  34. package/tests/init-workflow.test.mjs +31 -0
  35. package/tests/recommended-tools-pty.test.mjs +16 -0
  36. package/tests/recommended-tools.test.mjs +423 -0
  37. package/tests/resources.test.mjs +66 -0
  38. package/tests/skills-routing.test.mjs +7 -4
  39. package/tests/ui-tip-reload.test.mjs +70 -0
  40. package/tests/ui.test.mjs +450 -0
  41. package/tsconfig.json +1 -0
  42. package/eval/README.md +0 -72
  43. package/eval/permission-cases.json +0 -28
  44. package/eval/permissions.mjs +0 -103
  45. package/extensions/background-tasks.ts +0 -433
  46. package/extensions/background-worker.ts +0 -50
  47. package/extensions/glob.ts +0 -32
  48. package/extensions/mode.ts +0 -397
  49. package/lib/bash-approvals.ts +0 -113
  50. package/lib/bash-policy.ts +0 -164
  51. package/lib/mode-policy.ts +0 -174
  52. package/lib/path-policy.ts +0 -182
  53. package/lib/permission-classifier.ts +0 -128
  54. package/lib/permission-config.ts +0 -91
  55. package/lib/permission-denials.ts +0 -32
  56. package/lib/permission-intent.ts +0 -128
  57. package/lib/permission-taxonomy.ts +0 -15
  58. package/lib/task-broker.ts +0 -65
  59. package/lib/task-checkout.ts +0 -39
  60. package/lib/task-git.ts +0 -44
  61. package/lib/task-patch.ts +0 -106
  62. package/lib/task-permissions.ts +0 -51
  63. package/lib/task-report.ts +0 -62
  64. package/lib/task-worktree-policy.ts +0 -56
  65. package/skills/claude-api/SKILL.md +0 -572
  66. package/skills/claude-api/csharp/claude-api/README.md +0 -362
  67. package/skills/claude-api/csharp/claude-api/batches.md +0 -14
  68. package/skills/claude-api/csharp/claude-api/files-api.md +0 -25
  69. package/skills/claude-api/csharp/claude-api/streaming.md +0 -28
  70. package/skills/claude-api/csharp/claude-api/tool-use.md +0 -164
  71. package/skills/claude-api/curl/examples.md +0 -256
  72. package/skills/claude-api/curl/managed-agents.md +0 -371
  73. package/skills/claude-api/go/claude-api/README.md +0 -188
  74. package/skills/claude-api/go/claude-api/files-api.md +0 -23
  75. package/skills/claude-api/go/claude-api/streaming.md +0 -43
  76. package/skills/claude-api/go/claude-api/tool-use.md +0 -220
  77. package/skills/claude-api/go/managed-agents/README.md +0 -564
  78. package/skills/claude-api/java/claude-api/README.md +0 -238
  79. package/skills/claude-api/java/claude-api/files-api.md +0 -27
  80. package/skills/claude-api/java/claude-api/streaming.md +0 -24
  81. package/skills/claude-api/java/claude-api/tool-use.md +0 -228
  82. package/skills/claude-api/java/managed-agents/README.md +0 -443
  83. package/skills/claude-api/php/claude-api/README.md +0 -174
  84. package/skills/claude-api/php/claude-api/batches.md +0 -15
  85. package/skills/claude-api/php/claude-api/files-api.md +0 -13
  86. package/skills/claude-api/php/claude-api/streaming.md +0 -27
  87. package/skills/claude-api/php/claude-api/tool-use.md +0 -253
  88. package/skills/claude-api/php/managed-agents/README.md +0 -443
  89. package/skills/claude-api/python/claude-api/README.md +0 -565
  90. package/skills/claude-api/python/claude-api/batches.md +0 -198
  91. package/skills/claude-api/python/claude-api/files-api.md +0 -170
  92. package/skills/claude-api/python/claude-api/sdk-upgrade.md +0 -286
  93. package/skills/claude-api/python/claude-api/streaming.md +0 -179
  94. package/skills/claude-api/python/claude-api/tool-use.md +0 -627
  95. package/skills/claude-api/python/managed-agents/README.md +0 -335
  96. package/skills/claude-api/ruby/claude-api/README.md +0 -134
  97. package/skills/claude-api/ruby/claude-api/streaming.md +0 -16
  98. package/skills/claude-api/ruby/claude-api/tool-use.md +0 -41
  99. package/skills/claude-api/ruby/managed-agents/README.md +0 -394
  100. package/skills/claude-api/shared/admin-api.md +0 -179
  101. package/skills/claude-api/shared/agent-design.md +0 -101
  102. package/skills/claude-api/shared/anthropic-cli.md +0 -269
  103. package/skills/claude-api/shared/claude-platform-on-aws.md +0 -59
  104. package/skills/claude-api/shared/cost-optimization.md +0 -233
  105. package/skills/claude-api/shared/error-codes.md +0 -262
  106. package/skills/claude-api/shared/live-sources.md +0 -166
  107. package/skills/claude-api/shared/managed-agents-api-reference.md +0 -455
  108. package/skills/claude-api/shared/managed-agents-client-patterns.md +0 -220
  109. package/skills/claude-api/shared/managed-agents-core.md +0 -359
  110. package/skills/claude-api/shared/managed-agents-environments.md +0 -226
  111. package/skills/claude-api/shared/managed-agents-events.md +0 -290
  112. package/skills/claude-api/shared/managed-agents-memory.md +0 -201
  113. package/skills/claude-api/shared/managed-agents-multiagent.md +0 -260
  114. package/skills/claude-api/shared/managed-agents-onboarding.md +0 -82
  115. package/skills/claude-api/shared/managed-agents-outcomes.md +0 -108
  116. package/skills/claude-api/shared/managed-agents-overview.md +0 -77
  117. package/skills/claude-api/shared/managed-agents-scheduled-deployments.md +0 -156
  118. package/skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +0 -282
  119. package/skills/claude-api/shared/managed-agents-tools.md +0 -504
  120. package/skills/claude-api/shared/managed-agents-webhooks.md +0 -143
  121. package/skills/claude-api/shared/model-migration.md +0 -1872
  122. package/skills/claude-api/shared/models.md +0 -142
  123. package/skills/claude-api/shared/platform-availability.md +0 -53
  124. package/skills/claude-api/shared/prompt-audit.md +0 -223
  125. package/skills/claude-api/shared/prompt-caching.md +0 -292
  126. package/skills/claude-api/shared/token-counting.md +0 -56
  127. package/skills/claude-api/shared/tool-use-concepts.md +0 -526
  128. package/skills/claude-api/typescript/claude-api/README.md +0 -405
  129. package/skills/claude-api/typescript/claude-api/batches.md +0 -106
  130. package/skills/claude-api/typescript/claude-api/files-api.md +0 -98
  131. package/skills/claude-api/typescript/claude-api/streaming.md +0 -178
  132. package/skills/claude-api/typescript/claude-api/tool-use.md +0 -586
  133. package/skills/claude-api/typescript/managed-agents/README.md +0 -359
  134. package/tests/auto-permissions.test.mjs +0 -315
  135. package/tests/background-tasks.test.mjs +0 -27
  136. package/tests/background-worker.test.mjs +0 -60
  137. package/tests/bash-permissions.test.mjs +0 -276
  138. package/tests/glob.test.mjs +0 -31
  139. package/tests/mode.test.mjs +0 -62
  140. package/tests/permission-evaluation.test.mjs +0 -70
  141. package/tests/permission-foundation.test.mjs +0 -194
  142. package/tests/permission-policy.test.mjs +0 -158
  143. package/tests/runtime/README.md +0 -51
  144. package/tests/runtime/harness.mjs +0 -190
  145. package/tests/runtime/permissions.test.mjs +0 -192
  146. package/tests/runtime/tui.test.mjs +0 -60
  147. package/tests/task-integration.test.mjs +0 -324
  148. package/tests/task-permissions.test.mjs +0 -178
  149. package/tests/task-worktree-policy.test.mjs +0 -53
@@ -1,108 +0,0 @@
1
- # Managed Agents - Outcomes
2
-
3
- An **outcome** elevates a session from *conversation* to *work*: you state what "done" looks like, and the harness runs an iterate -> grade -> revise loop until the artifact meets the rubric, hits `max_iterations`, or is interrupted. A separate **grader** (independent context window) scores each iteration against your rubric and feeds per-criterion gaps back to the agent.
4
-
5
- The SDK sets the `managed-agents-2026-04-01` beta header automatically on all `client.beta.sessions.*` calls; no additional header is required for outcomes.
6
-
7
- ---
8
-
9
- ## The `user.define_outcome` event
10
-
11
- Outcomes are not a field on `sessions.create()`. You create a normal session, then send a `user.define_outcome` event. The agent starts working on receipt - **do not also send a `user.message`** to kick it off.
12
-
13
- You can collapse both calls into one by passing a single `user.define_outcome` in the session's `initial_events` array - same event, same rules, one round trip (see `shared/managed-agents-core.md` -> Seeding a session with `initial_events`). More than one `user.define_outcome` in that array, or one without a `rubric`, rejects the whole create with a 400.
14
-
15
- ```python
16
- session = client.beta.sessions.create(
17
- agent=AGENT_ID,
18
- environment_id=ENVIRONMENT_ID,
19
- title="Financial analysis on Costco",
20
- )
21
-
22
- client.beta.sessions.events.send(
23
- session_id=session.id,
24
- events=[
25
- {
26
- "type": "user.define_outcome",
27
- "description": "Build a DCF model for Costco in .xlsx",
28
- "rubric": {"type": "text", "content": RUBRIC_MD},
29
- # or: "rubric": {"type": "file", "file_id": rubric.id}
30
- "max_iterations": 5, # optional; default 3, max 20
31
- }
32
- ],
33
- )
34
- ```
35
-
36
- | Field | Type | Notes |
37
- |---|---|---|
38
- | `type` | `"user.define_outcome"` | |
39
- | `description` | string | The task. This is what the agent works toward - no separate `user.message` needed. |
40
- | `rubric` | `{type: "text", content}` \| `{type: "file", file_id}` | **Required.** Markdown with explicit, independently gradeable criteria. Upload once via `client.beta.files.upload(...)` (beta `files-api-2025-04-14`) to reuse across sessions. |
41
- | `max_iterations` | int | Optional. Default **3**, max **20**. |
42
-
43
- The event is echoed back on the stream with a server-assigned `outcome_id` and `processed_at`.
44
-
45
- > **Writing rubrics.** Use explicit, gradeable criteria ("CSV has a numeric `price` column"), not vibes ("data looks good") - the grader scores each criterion independently, so vague criteria produce noisy loops. If you don't have a rubric, have Claude analyze a known-good artifact and turn that analysis into one.
46
-
47
- ---
48
-
49
- ## Outcome-specific events
50
-
51
- These appear on the standard event stream (`sessions.events.stream` / `.list`) alongside the usual `agent.*` / `session.*` events.
52
-
53
- | Event | Payload highlights | Meaning |
54
- |---|---|---|
55
- | `span.outcome_evaluation_start` | `outcome_id`, `iteration` (0-indexed) | Grader began scoring iteration *N*. |
56
- | `span.outcome_evaluation_ongoing` | `outcome_id` | Heartbeat while the grader runs. Grader reasoning is opaque - you see *that* it's working, not *what* it's thinking. |
57
- | `span.outcome_evaluation_end` | `outcome_evaluation_start_id`, `outcome_id`, `iteration`, `result`, `explanation`, `usage` | Grader finished one iteration. `result` drives what happens next (table below). |
58
-
59
- ### `span.outcome_evaluation_end.result`
60
-
61
- | `result` | Next |
62
- |---|---|
63
- | `satisfied` | Session -> `idle`. Terminal for this outcome. |
64
- | `needs_revision` | Agent starts another iteration. |
65
- | `max_iterations_reached` | No further grader cycles. Agent may run one final revision, then session -> `idle`. |
66
- | `failed` | Session -> `idle`. Rubric fundamentally doesn't match the task (e.g. description and rubric contradict). |
67
- | `interrupted` | Emitted whenever a `user.interrupt` arrives while an outcome is active - **even if evaluation hadn't started**. In that case `outcome_evaluation_start_id` is an empty string rather than an event ID, so don't use it as a lookup key without checking. (Except an interrupt sent while paused at the session budget, which is accepted and ignored - see `shared/managed-agents-events.md` § Reaching a session budget.) |
68
-
69
- ```json
70
- {
71
- "type": "span.outcome_evaluation_end",
72
- "id": "sevt_01jkl...",
73
- "outcome_evaluation_start_id": "sevt_01def...",
74
- "outcome_id": "outc_01a...",
75
- "result": "satisfied",
76
- "explanation": "All 12 criteria met: revenue projections use 5 years of historical data, ...",
77
- "iteration": 0,
78
- "usage": { "input_tokens": 2400, "output_tokens": 350, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 1800 },
79
- "processed_at": "2026-03-25T14:03:00Z"
80
- }
81
- ```
82
-
83
- ---
84
-
85
- ## Checking status & retrieving deliverables
86
-
87
- **Status** - either watch the stream for `span.outcome_evaluation_end`, or poll the session and read `outcome_evaluations`:
88
-
89
- ```python
90
- session = client.beta.sessions.retrieve(session.id)
91
- for ev in session.outcome_evaluations:
92
- print(f"{ev.outcome_id}: {ev.result}") # outc_01a...: satisfied
93
- ```
94
-
95
- **Deliverables** - the agent writes to `/mnt/session/outputs/`. Once idle, fetch via the Files API with `scope_id=session.id`. This is the same session-outputs mechanism documented in `shared/managed-agents-environments.md` -> Session outputs (including the dual-beta-header requirement on `files.list`).
96
-
97
- ---
98
-
99
- ## Interaction rules & pitfalls
100
-
101
- - **One outcome at a time.** Chain by sending the next `user.define_outcome` only after the previous one's terminal `span.outcome_evaluation_end` (`satisfied` / `max_iterations_reached` / `failed` / `interrupted`). The session retains history across chained outcomes.
102
- - **Steering is allowed but optional.** You *may* send `user.message` events mid-outcome to nudge direction, but the agent already knows to keep working until terminal - don't send "keep going" prompts. (Exception: a session paused at its budget (`stop_reason: budget_reached`) accepts only settle events - a steering `user.message`, or a chained `user.define_outcome`, is a 400 there; see `shared/managed-agents-events.md` § Reaching a session budget.)
103
- - **`user.interrupt` pauses the current outcome** - it marks `result: "interrupted"` and leaves the session `idle`, ready for a new outcome or conversational turn. (Exception: sent while paused at the session budget, the interrupt is accepted and ignored and the outcome stays active - see `shared/managed-agents-events.md` § Reaching a session budget.)
104
- - **After terminal, the session is reusable** - continue conversationally or define a new outcome.
105
- - **Outcome != session-create field.** Don't put `outcome`, `rubric`, or `description` on `sessions.create()` - outcomes are always sent as a `user.define_outcome` event.
106
- - **Idle-break gate is unchanged.** In your drain loop, keep using `event.type === 'session.status_idle' && event.stop_reason?.type !== 'requires_action'` - do **not** gate on `span.outcome_evaluation_end` alone (on `needs_revision` the session keeps running). See `shared/managed-agents-client-patterns.md` Pattern 5.
107
-
108
- For the raw HTTP shapes and per-language SDK bindings beyond Python, WebFetch `https://platform.claude.com/docs/en/managed-agents/define-outcomes.md` (see `shared/live-sources.md`).
@@ -1,77 +0,0 @@
1
- # Managed Agents - Overview
2
-
3
- Managed Agents provisions a container per session as the agent's workspace. The agent loop runs on Anthropic's orchestration layer; the container is where the agent's *tools* execute - bash commands, file operations, code. You create a persisted **Agent** config (model, system prompt, tools, MCP servers, skills), then start **Sessions** that reference it. The session streams events back to you; you send user messages and tool results in.
4
-
5
- ## Warning: THE MANDATORY FLOW: Agent (once) -> Session (every run)
6
-
7
- **Why agents are separate objects: versioning.** An agent is a persisted, versioned config - every update creates a new immutable version, and sessions pin to a version at creation time. This lets you iterate on the agent (tweak the prompt, add a tool) without breaking sessions already running, roll back if a change regresses, and A/B test versions side-by-side. None of that works if you `agents.create()` fresh on every run.
8
-
9
- Every session references a pre-created `/v1/agents` object. Create the agent once, store the ID, and reuse it across runs.
10
-
11
- | Step | Call | Frequency |
12
- |---|---|---|
13
- | 1 | `POST /v1/agents` - `model`, `system`, `tools`, `mcp_servers`, `skills` live here | **ONCE.** Store `agent.id` **and** `agent.version`. |
14
- | 2 | `POST /v1/sessions` - `agent: "agent_abc123"` or `{type: "agent", id, version}` | **Every run.** String shorthand uses latest version. |
15
-
16
- If you're about to write `sessions.create()` with `model`, `system`, or `tools` on the session body - **stop**. Those fields live on `agents.create()`. The session takes a *pointer* only.
17
-
18
- **When generating code, separate setup from runtime.** `agents.create()` belongs in a setup script (or a guarded `if agent_id is None:` block), not at the top of the hot path. If the user's code calls `agents.create()` on every invocation, they're accumulating orphaned agents and paying the create latency for nothing. The correct shape is: define the agent as a version-controlled YAML manifest, apply it once with `ant beta:agents create < agent.yaml` (or a guarded setup script - see `shared/anthropic-cli.md`), persist the returned ID (config file, env var, secrets manager), and have every run load the ID and call `sessions.create()`.
19
-
20
- **To change the agent's behavior, use `POST /v1/agents/{id}` - don't create a new one.** Each update bumps the version; running sessions keep their pinned version, new sessions get the latest (or pin explicitly via `{type: "agent", id, version}`). See `shared/managed-agents-core.md` -> Agents -> Versioning. To change `tools`/`mcp_servers` on **one running session** without touching the agent object, use `sessions.update()` (`vault_ids` attaches at session create only) - see `shared/managed-agents-core.md` -> Updating the agent configuration mid-session.
21
-
22
- ## Beta Headers
23
-
24
- Managed Agents is in beta. The SDK sets required beta headers automatically:
25
-
26
- | Beta Header | What it enables |
27
- | ------------------------------ | ---------------------------------------------------- |
28
- | `managed-agents-2026-04-01` | Agents, Environments, Sessions, Events, Session Resources, Session Threads, Outcomes, Multiagent, Vaults, Credentials, Memory Stores, Deployments |
29
- | `skills-2025-10-02` | Skills API (for managing custom skill definitions) |
30
- | `files-api-2025-04-14` | Files API for file uploads |
31
-
32
- **Which beta header goes where:** The SDK sets `managed-agents-2026-04-01` automatically on `client.beta.{agents,environments,sessions,vaults,memory_stores,deployments,deployment_runs}.*` calls, and `files-api-2025-04-14` / `skills-2025-10-02` automatically on `client.beta.files.*` / `client.beta.skills.*` calls. You do NOT need to add the Skills or Files beta header when calling Managed Agents endpoints. On raw HTTP the Managed Agents header **grants Files API access on its own**, so uploading a file for use as a session resource does not need `files-api-2025-04-14` alongside it. (Direct Skills API calls over cURL do still need `skills-2025-10-02`; the `ant` CLI and the SDKs send it for you.) **Exception - session-scoped file listing:** `client.beta.files.list({scope_id: session.id})` is a Files endpoint that takes a Managed Agents parameter, so it needs **both** headers. Pass `betas: ["managed-agents-2026-04-01"]` explicitly on that call (the SDK adds the Files header; you add the Managed Agents one). See `shared/managed-agents-environments.md` -> Session outputs.
33
-
34
-
35
- ## Reading Guide
36
-
37
- | User wants to... | Read these files |
38
- | -------------------------------------- | ------------------------------------------------------- |
39
- | **Get started from scratch / "help me set up an agent"** | `shared/managed-agents-onboarding.md` - guided interview (WHERE->WHO->WHAT->WATCH), then emit code |
40
- | Understand how the API works | `shared/managed-agents-core.md` |
41
- | See the full endpoint reference | `shared/managed-agents-api-reference.md` |
42
- | **Create an agent** (required first step) | `shared/managed-agents-core.md` (Agents section) + language file |
43
- | Update/version an agent | `shared/managed-agents-core.md` (Agents -> Versioning) - update, don't re-create |
44
- | Create a session | `shared/managed-agents-core.md` + `{lang}/managed-agents/README.md` (cURL/C#: `curl/managed-agents.md`) |
45
- | Configure tools and permissions | `shared/managed-agents-tools.md` |
46
- | Restrict which sites `web_search` / `web_fetch` can reach; localize search; cap fetched content | `shared/managed-agents-tools.md` (§ Web search & web fetch settings) - `allowed_domains` / `blocked_domains` / `user_location` / `max_content_tokens` on the toolset `configs` entry; **not** the environment's `networking` |
47
- | Set up MCP servers | `shared/managed-agents-tools.md` (MCP Servers section) |
48
- | Stream events / handle tool_use | `shared/managed-agents-events.md` + language file |
49
- | Get notified of session state changes via webhook (no polling) | `shared/managed-agents-webhooks.md` - Console-registered endpoint, HMAC verify, thin payload + fetch |
50
- | Define an outcome / rubric-graded iterate loop | `shared/managed-agents-outcomes.md` - `user.define_outcome` event, grader, `span.outcome_evaluation_*` events |
51
- | Coordinate multiple agents / subagents / threads | `shared/managed-agents-multiagent.md` - `multiagent: {type: "coordinator", agents: [...]}` on the agent, session threads, cross-posted tool confirmations |
52
- | Set up environments | `shared/managed-agents-environments.md` + language file |
53
- | Run tool execution in your own infra / VPC (self-hosted sandbox) | `shared/managed-agents-self-hosted-sandboxes.md` - `config:{type:"self_hosted"}`, `ANTHROPIC_ENVIRONMENT_KEY`, `EnvironmentWorker.run()` / `ant beta:worker poll` |
54
- | Upload files / attach repos | `shared/managed-agents-environments.md` (Resources) |
55
- | Give agents persistent memory across sessions | `shared/managed-agents-memory.md` - memory stores, `memory_store` session resource, preconditions, versions/redact. On self-hosted sandboxes: `shared/managed-agents-self-hosted-sandboxes.md` § Memory stores (SDK worker syncs a local copy) |
56
- | Inspect a session without code (transcript, per-tool stats, cost, threads) | `shared/managed-agents-events.md` - Console session viewer note; deep link `?event={event_id}` |
57
- | Define agents/environments as version-controlled YAML; drive the API from the shell | `shared/anthropic-cli.md` - `ant beta:agents create < agent.yaml`, `--transform`, `@file` inlining |
58
- | Store credentials (MCP auth, API keys for CLIs/SDKs) | `shared/managed-agents-tools.md` (Vaults section) - `mcp_oauth` / `static_bearer` / `environment_variable` |
59
- | Call a non-MCP API / CLI that needs a secret | `shared/managed-agents-tools.md` (Vaults section) - `environment_variable` credential, substituted at egress. If that doesn't fit (e.g. self-hosted sandboxes), `shared/managed-agents-client-patterns.md` Pattern 9 keeps the secret host-side via a custom tool |
60
- | Run an agent on a recurring cron schedule | `shared/managed-agents-scheduled-deployments.md` - deployments, deployment runs, pause/auto-pause |
61
- | Cap a session's spend with a hard dollar budget | `shared/managed-agents-core.md` (§ Session budgets) - `budget` at session create, `budget_reached` pause, change/remove to resume. Deployments: `shared/managed-agents-scheduled-deployments.md` § Deployment budgets |
62
- | Pin where model inference runs (data residency) | `shared/managed-agents-core.md` (§ Pinning inference geography) - `model.inference_geo` on the agent, per-session override, roster uniformity |
63
- | Load skills from the codebase instead of uploading | `shared/managed-agents-tools.md` (§ Skills from a GitHub repository) - root `.claude/skills` discovery at session start |
64
- | Give the session an advisor to consult mid-turn | `shared/managed-agents-multiagent.md` (§ Advisor) - `{type: "advisor", model}` roster entry, consultation threads, plaintext vs redacted delivery |
65
-
66
- ## Common Pitfalls
67
-
68
- - **Agent FIRST, then session - NO EXCEPTIONS** - the session's `agent` field accepts **only** a string ID or `{type: "agent", id, version}`. `model`, `system`, `tools`, `mcp_servers`, `skills` are **top-level fields on `POST /v1/agents`**, never on `sessions.create()`. If the user hasn't created an agent, that is step zero of every example.
69
- - **Agent ONCE, not every run** - `agents.create()` is a setup step. Store the returned `agent_id` and reuse it; don't call `agents.create()` at the top of your hot path. If the agent's config needs to change, `POST /v1/agents/{id}` - each update creates a new version, and sessions can pin to a specific version for reproducibility.
70
- - **MCP auth goes through vaults** - the agent's `mcp_servers` array declares `{type, name, url}` only (no auth). Credentials live in vaults (`client.beta.vaults.credentials.create`) and attach to sessions via `vault_ids`. Anthropic auto-refreshes OAuth tokens using the stored refresh token. Vaults also hold `environment_variable` credentials for non-MCP services (CLIs, SDKs, direct API calls) - substituted at egress, never visible in the sandbox.
71
- - **Reconcile resources before the first run** - a session with a clear ask but a missing tool, credential, data mount, or context will discover the gap mid-run, then flail and give up. Before creating the session, check that every action in the task maps to a configured tool/MCP server, every MCP server has a vault credential, and every referenced file/host is mounted/reachable. When helping a user set one up, run the reconciliation in `shared/managed-agents-onboarding.md` -> §3 Pre-flight viability check.
72
- - **Stream to get events** - `GET /v1/sessions/{id}/events/stream` is the primary way to receive agent output in real-time.
73
- - **SSE stream has no replay - reconnect with consolidation** - if the stream drops while a `agent.tool_use`, `agent.mcp_tool_use`, or `agent.custom_tool_use` is pending resolution (`user.tool_confirmation` for the first two, `user.custom_tool_result` for the last one), the session deadlocks (client disconnects -> session idles -> reconnect happens -> no client resolution happens). On every (re)connect: open stream with `GET /v1/sessions/{id}/events/stream` , fetch `GET /v1/sessions/{id}/events`, dedupe by event ID, then proceed. See `shared/managed-agents-events.md` -> Reconnecting after a dropped stream.
74
- - **Don't trust HTTP-library timeouts as wall-clock caps** - `requests` `timeout=(c, r)` and `httpx.Timeout(n)` are *per-chunk* read timeouts; they reset every byte, so a trickling connection can block indefinitely. For a hard deadline on raw-HTTP polling, track `time.monotonic()` at the loop level and bail explicitly. Prefer the SDK's `sessions.events.stream()` / `sessions.events.list()` over hand-rolled HTTP. See `shared/managed-agents-events.md` -> Receiving Events.
75
- - **Messages queue** - you can send events while the session is `running` or `idle`; they're processed in order. No need to wait for a response before sending the next message. Exception: a session paused at its budget (`stop_reason: budget_reached`) accepts only settle events - change or remove the budget to resume (`shared/managed-agents-core.md` § Session budgets).
76
- - **Environment `config.type` is `"cloud"` or `"self_hosted"`** - `cloud` runs the container on Anthropic's infrastructure; `self_hosted` moves tool execution to your own (see `shared/managed-agents-self-hosted-sandboxes.md`).
77
- - **Archive is permanent on every resource** - archiving an agent, environment, session, vault, credential, or memory store makes it read-only with no unarchive. For agents, environments, and memory stores specifically, archived resources cannot be referenced by new sessions (existing sessions continue). Do not call `.archive()` on a production agent, environment, or memory store as cleanup - **always confirm with the user before archiving**.
@@ -1,156 +0,0 @@
1
- # Managed Agents - Scheduled Deployments
2
-
3
- A **scheduled deployment** runs an agent on a recurring cron schedule - each firing creates a session autonomously. Use it for predictable-cadence work: nightly triage, weekly compliance scans, hourly monitors.
4
-
5
- Requires the `managed-agents-2026-04-01` beta header (the SDK sets it automatically for `client.beta.deployments.*` / `client.beta.deployment_runs.*` calls).
6
-
7
- ## Create a deployment
8
-
9
- A deployment bundles everything a session needs (agent, environment, optional files / GitHub / memory stores / vaults) plus a `schedule` and the `initial_events` that kick off each run:
10
-
11
- - `agent` and `environment_id` are required - same shapes as `sessions.create` (see `shared/managed-agents-core.md`). A deployment targeting a **self-hosted** environment can attach `memory_store` resources (SDK worker required - `shared/managed-agents-self-hosted-sandboxes.md` § Memory stores); `file` and `github_repository` resources need a cloud environment. The Console deployment form doesn't offer memory stores for self-hosted environments - attach them via the API/SDK.
12
- - `initial_events` must contain at least one starting event - a `user.message` **or** a `user.define_outcome`. (A deployment's `initial_events` also accepts `system.message`, which a session's does not.)
13
- - `schedule` takes a cron `expression` and an IANA `timezone`. Minute-level granularity is the maximum.
14
-
15
- ```bash
16
- curl -fsSL https://api.anthropic.com/v1/deployments \
17
- -H "x-api-key: $ANTHROPIC_API_KEY" \
18
- -H "anthropic-version: 2023-06-01" \
19
- -H "anthropic-beta: managed-agents-2026-04-01" \
20
- -H "content-type: application/json" \
21
- -d @- <<EOF
22
- {
23
- "name": "Weekly compliance scan",
24
- "agent": "$AGENT_ID",
25
- "environment_id": "$ENVIRONMENT_ID",
26
- "initial_events": [
27
- {"type": "user.message", "content": [{"type": "text", "text": "Run the weekly compliance scan."}]}
28
- ],
29
- "schedule": {
30
- "type": "cron",
31
- "expression": "0 20 * * 5",
32
- "timezone": "America/New_York"
33
- }
34
- }
35
- EOF
36
- ```
37
-
38
- ```python
39
- deployment = client.beta.deployments.create(
40
- name="Weekly compliance scan",
41
- agent=agent.id,
42
- environment_id=environment.id,
43
- initial_events=[
44
- {
45
- "type": "user.message",
46
- "content": [{"type": "text", "text": "Run the weekly compliance scan."}],
47
- },
48
- ],
49
- schedule={
50
- "type": "cron",
51
- "expression": "0 20 * * 5",
52
- "timezone": "America/New_York",
53
- },
54
- )
55
- ```
56
-
57
- The response is a deployment object (`depl_` ID prefix). Check `schedule.upcoming_runs_at` - the next fire times - to confirm the schedule parses the way you intended:
58
-
59
- ```json
60
- {
61
- "id": "depl_01xyz",
62
- "status": "active",
63
- "paused_reason": null,
64
- "schedule": {
65
- "type": "cron",
66
- "expression": "0 20 * * 5",
67
- "timezone": "America/New_York",
68
- "last_run_at": null,
69
- "upcoming_runs_at": ["2026-05-09T00:00:00Z", "2026-05-16T00:00:00Z", "2026-05-23T00:00:00Z"]
70
- }
71
- }
72
- ```
73
-
74
- `upcoming_runs_at` reflects the exact configured schedule, but **execution is jittered to distribute load: up to 15% of the interval between runs, floored at 5 seconds and capped at 9 minutes.** An hourly deployment can therefore fire up to 9 minutes late; don't build a downstream deadline that assumes the listed timestamp. Maximum **1000 scheduled deployments per organization** (contact Anthropic support for more).
75
-
76
- ### Cron and timezone semantics
77
-
78
- - **Expression:** standard POSIX cron (`minute hour day-of-month month day-of-week`).
79
- - **Timezone:** IANA identifier (e.g. `"America/Los_Angeles"`).
80
- - **DST:** literal wall-clock matching - `"0 20 * * *"` in `America/New_York` fires at 8:00 PM local regardless of EST/EDT.
81
-
82
- > Warning: **DST edge:** wall-clock times that don't exist on a spring-forward day (e.g. 2AM) are **skipped**; times that occur twice on a fall-back day **fire twice**. Schedule outside the 1-3AM local window, or use UTC, when missed or duplicate executions are unacceptable.
83
-
84
- ## Deployment budgets
85
-
86
- A deployment accepts the same `budget` object as a session (`{type: "limit", max_list_cost: {amount, currency}}` - minor-unit cents string, `USD` only; see `shared/managed-agents-core.md` § Session budgets). The cap is **copied onto each session at fire time**, and that session then behaves exactly like any budgeted session.
87
-
88
- Deployment budget update semantics differ from a session's:
89
-
90
- - `budget` is accepted on **create and update** - it is not create-only.
91
- - `budget: null` on update **clears** it, and a cleared budget **can be re-added later** - there is no one-way door.
92
- - A change applies **from the next fired session** - sessions already running keep the cap they were created with (change those via their own session update).
93
-
94
- ## Deployment runs
95
-
96
- Every trigger attempt - successful or not - writes a **deployment run** record (`drun_` prefix), so you can audit failures independent of the session lifecycle. A successful run carries the created `session_id`; follow that session via the event stream (`shared/managed-agents-events.md`) or webhooks (`shared/managed-agents-webhooks.md`) as usual. A failed run carries an `error` whose `type` explains why session creation was rejected.
97
-
98
- ```python
99
- # All runs for a deployment
100
- for run in client.beta.deployment_runs.list(deployment_id=deployment.id):
101
- print(run.created_at, run.session_id or run.error.type)
102
-
103
- # Failures only
104
- for run in client.beta.deployment_runs.list(deployment_id=deployment.id, has_error=True):
105
- print(run.created_at, run.error.type, run.error.message)
106
- ```
107
-
108
- ```typescript
109
- for await (const run of client.beta.deploymentRuns.list({
110
- deployment_id: deployment.id,
111
- has_error: true,
112
- })) {
113
- console.log(run.created_at, run.error?.type, run.error?.message);
114
- }
115
- ```
116
-
117
- Raw HTTP: `GET /v1/deployment_runs?deployment_id=...&has_error=true`. To retrieve a single run by ID, `GET /v1/deployment_runs/{deployment_run_id}` (SDK: `client.beta.deployment_runs.retrieve(run_id)`) - a `deployment_run.*` webhook event carries the run ID as its `data.id`.
118
-
119
- A failed run looks like:
120
-
121
- ```json
122
- {
123
- "type": "deployment_run",
124
- "id": "drun_01abc124",
125
- "deployment_id": "depl_01xyz",
126
- "trigger_context": { "type": "schedule", "scheduled_at": "2026-05-09T00:00:00Z" },
127
- "session_id": null,
128
- "error": { "type": "environment_archived", "message": "environment `env_01abc` is archived" },
129
- "agent": { "type": "agent", "id": "agent_01ghi789", "version": 3 },
130
- "created_at": "2026-05-09T00:00:01Z"
131
- }
132
- ```
133
-
134
- Error types include `environment_archived`, `agent_archived`, `vault_not_found`, `session_rate_limited`, and `service_unavailable`.
135
-
136
- The outcome of each **scheduled** run (started/succeeded/failed) and each deployment lifecycle change (created/updated/paused/unpaused/archived/deleted) is also delivered as a webhook event - see `shared/managed-agents-webhooks.md` for the `deployment.*` and `deployment_run.*` event types - so you can react without polling. Manual runs do **not** emit `deployment_run.*` webhook events.
137
-
138
- ## Lifecycle: pause / unpause / archive
139
-
140
- | Operation | SDK | Effect |
141
- |---|---|---|
142
- | Pause | `client.beta.deployments.pause(id)` | Suppresses scheduled triggers go-forward. Sessions already running continue. **Manual runs are still permitted while paused.** Sets `paused_reason: {"type": "manual"}`. |
143
- | Unpause | `client.beta.deployments.unpause(id)` | Resumes from the next scheduled occurrence. **Missed triggers are not backfilled.** Clears `paused_reason`. |
144
- | Archive | `client.beta.deployments.archive(id)` | **Terminal** - the schedule stops and the deployment can no longer be modified. Use pause for anything reversible. |
145
-
146
- Raw HTTP: `POST /v1/deployments/{deployment_id}/pause` (likewise `/unpause`, `/archive`).
147
-
148
- ### Failure behavior
149
-
150
- - **Rate-limited:** recorded immediately as a `session_rate_limited` run, **no retry** - the schedule simply tries again at the next occurrence. (Rate limits on API calls *inside* a session are handled by the session itself.)
151
- - **Other failed runs** (e.g. `environment_archived`, `vault_not_found`, `service_unavailable`): the run records the `error.type` - monitor runs and fix the referenced resource, or pause the deployment.
152
- - **Agent archived:** the deployment is automatically **archived** (terminal) in the same operation. **Agent deleted:** the next scheduled trigger detects the missing agent and archives the deployment then. Either way no deployment run is recorded, and no further sessions are created.
153
-
154
- ## Manual runs
155
-
156
- `POST /v1/deployments/{deployment_id}/run` (SDK: `client.beta.deployments.run(id)`) creates a session immediately and writes a run with `trigger_context.type: "manual"`. Use it to **test a deployment before committing to the schedule** - and remember it works even while the deployment is paused.