@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,253 +0,0 @@
1
- # Tool Use - PHP
2
-
3
- For conceptual overview (tool definitions, tool choice, tips), see [shared/tool-use-concepts.md](../../shared/tool-use-concepts.md).
4
-
5
- ## Tool Use
6
-
7
- ### Tool Runner (Beta)
8
-
9
- **Beta:** The PHP SDK provides a tool runner via `$client->beta->messages->toolRunner()`. Define tools with `BetaRunnableTool` - a definition array plus a `run` closure:
10
-
11
- ```php
12
- use Anthropic\Lib\Tools\BetaRunnableTool;
13
-
14
- $weatherTool = new BetaRunnableTool(
15
- definition: [
16
- 'name' => 'get_weather',
17
- 'description' => 'Get the current weather for a location.',
18
- 'inputSchema' => [
19
- 'type' => 'object',
20
- 'properties' => [
21
- 'location' => ['type' => 'string', 'description' => 'City and state'],
22
- ],
23
- 'required' => ['location'],
24
- ],
25
- ],
26
- run: function (array $input): string {
27
- return "The weather in {$input['location']} is sunny and 72°F.";
28
- },
29
- );
30
-
31
- $runner = $client->beta->messages->toolRunner(
32
- maxTokens: 16000,
33
- messages: [['role' => 'user', 'content' => 'What is the weather in Paris?']],
34
- model: 'claude-opus-5',
35
- tools: [$weatherTool],
36
- );
37
-
38
- foreach ($runner as $message) {
39
- foreach ($message->content as $block) {
40
- if ($block->type === 'text') {
41
- echo $block->text;
42
- }
43
- }
44
- }
45
- ```
46
-
47
- ### Manual Loop
48
-
49
- Tools are passed as arrays. **The SDK uses camelCase keys** (`inputSchema`, `toolUseID`, `stopReason`) and auto-maps to the API's snake_case on the wire - since v0.5.0. See [shared tool use concepts](../../shared/tool-use-concepts.md) for the loop pattern.
50
-
51
- ```php
52
- use Anthropic\Messages\ToolUseBlock;
53
-
54
- $tools = [
55
- [
56
- 'name' => 'get_weather',
57
- 'description' => 'Get the current weather in a given location',
58
- 'inputSchema' => [ // camelCase, not input_schema
59
- 'type' => 'object',
60
- 'properties' => [
61
- 'location' => ['type' => 'string', 'description' => 'City and state'],
62
- ],
63
- 'required' => ['location'],
64
- ],
65
- ],
66
- ];
67
-
68
- $messages = [['role' => 'user', 'content' => 'What is the weather in SF?']];
69
-
70
- $response = $client->messages->create(
71
- model: 'claude-opus-5',
72
- maxTokens: 16000,
73
- tools: $tools,
74
- messages: $messages,
75
- );
76
-
77
- while ($response->stopReason === 'tool_use') { // camelCase property
78
- $toolResults = [];
79
- foreach ($response->content as $block) {
80
- if ($block instanceof ToolUseBlock) {
81
- // $block->name : string - tool name to dispatch on
82
- // $block->input : array<string,mixed> - parsed JSON input
83
- // $block->id : string - pass back as toolUseID
84
- $result = executeYourTool($block->name, $block->input);
85
- $toolResults[] = [
86
- 'type' => 'tool_result',
87
- 'toolUseID' => $block->id, // camelCase, not tool_use_id
88
- 'content' => $result,
89
- ];
90
- }
91
- }
92
-
93
- // Append assistant turn + user turn with tool results
94
- $messages[] = ['role' => 'assistant', 'content' => $response->content];
95
- $messages[] = ['role' => 'user', 'content' => $toolResults];
96
-
97
- $response = $client->messages->create(
98
- model: 'claude-opus-5',
99
- maxTokens: 16000,
100
- tools: $tools,
101
- messages: $messages,
102
- );
103
- }
104
-
105
- // Final text response
106
- foreach ($response->content as $block) {
107
- if ($block->type === 'text') {
108
- echo $block->text;
109
- }
110
- }
111
- ```
112
-
113
- `$block->type === 'tool_use'` also works; `instanceof ToolUseBlock` narrows for PHPStan.
114
-
115
-
116
- ---
117
-
118
- ## Structured Outputs
119
-
120
- ### Using StructuredOutputModel (Recommended)
121
-
122
- Define a PHP class implementing `StructuredOutputModel` and pass it as `outputConfig`:
123
-
124
- ```php
125
- use Anthropic\Lib\Contracts\StructuredOutputModel;
126
- use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
127
- use Anthropic\Lib\Attributes\Constrained;
128
-
129
- class Person implements StructuredOutputModel
130
- {
131
- use StructuredOutputModelTrait;
132
-
133
- #[Constrained(description: 'Full name')]
134
- public string $name;
135
-
136
- public int $age;
137
-
138
- public ?string $email = null; // nullable = optional field
139
- }
140
-
141
- $message = $client->messages->create(
142
- model: 'claude-opus-5',
143
- maxTokens: 16000,
144
- messages: [['role' => 'user', 'content' => 'Generate a profile for Alice, age 30']],
145
- outputConfig: ['format' => Person::class],
146
- );
147
-
148
- $person = $message->parsedOutput(); // Person instance
149
- echo $person->name;
150
- ```
151
-
152
- Types are inferred from PHP type hints. Use `#[Constrained(description: '...')]` to add descriptions. Nullable properties (`?string`) become optional fields.
153
-
154
- ### Raw Schema
155
-
156
- ```php
157
- $message = $client->messages->create(
158
- model: 'claude-opus-5',
159
- maxTokens: 16000,
160
- messages: [['role' => 'user', 'content' => 'Extract: John (john@co.com), Enterprise plan']],
161
- outputConfig: [
162
- 'format' => [
163
- 'type' => 'json_schema',
164
- 'schema' => [
165
- 'type' => 'object',
166
- 'properties' => [
167
- 'name' => ['type' => 'string'],
168
- 'email' => ['type' => 'string'],
169
- 'plan' => ['type' => 'string'],
170
- ],
171
- 'required' => ['name', 'email', 'plan'],
172
- 'additionalProperties' => false,
173
- ],
174
- ],
175
- ],
176
- );
177
-
178
- // First text block contains valid JSON
179
- foreach ($message->content as $block) {
180
- if ($block->type === 'text') {
181
- $data = json_decode($block->text, true);
182
- break;
183
- }
184
- }
185
- ```
186
-
187
- ---
188
-
189
- ## Beta Features & Anthropic-Defined Tools
190
-
191
- **`betas:` is NOT a param on `$client->messages->create()`** - it only exists on the beta namespace. Use it for features that need an explicit opt-in header:
192
-
193
- ```php
194
- use Anthropic\Beta\Messages\BetaRequestMCPServerURLDefinition;
195
-
196
- $response = $client->beta->messages->create(
197
- model: 'claude-opus-5',
198
- maxTokens: 16000,
199
- mcpServers: [
200
- BetaRequestMCPServerURLDefinition::with(
201
- name: 'my-server',
202
- url: 'https://example.com/mcp',
203
- ),
204
- ],
205
- betas: ['mcp-client-2025-11-20'], // only valid on ->beta->messages
206
- messages: [['role' => 'user', 'content' => 'Use the MCP tools']],
207
- );
208
- ```
209
-
210
- ### Task budgets
211
-
212
- ```php
213
- $response = $client->beta->messages->create(
214
- model: 'claude-opus-5',
215
- maxTokens: 16000,
216
- outputConfig: ['taskBudget' => ['type' => 'tokens', 'total' => 64000]],
217
- tools: [...],
218
- messages: [...],
219
- betas: ['task-budgets-2026-03-13'],
220
- );
221
- ```
222
-
223
- ### Cache diagnostics
224
-
225
- Pass the previous response's `id` on the next request; print the `diagnostics` object on the response:
226
-
227
- ```php
228
- $r2 = $client->beta->messages->create(
229
- model: 'claude-opus-5', maxTokens: 1024,
230
- diagnostics: ['previousMessageId' => $r1->id],
231
- betas: ['cache-diagnosis-2026-04-07'],
232
- messages: [...],
233
- );
234
- ```
235
-
236
- **Anthropic-defined tools** (bash, web_search, text_editor, code_execution) are GA and work on both paths. Of these, web_search and code_execution are server-executed; bash and text_editor are client-executed (you handle the `tool_use` locally) - `Anthropic\Messages\ToolBash20250124` / `WebSearchTool20260209` / `ToolTextEditor20250728` / `CodeExecutionTool20260120` for non-beta, `Anthropic\Beta\Messages\BetaToolBash20250124` / `BetaWebSearchTool20260209` / `BetaToolTextEditor20250728` / `BetaCodeExecutionTool20260120` for beta. No `betas:` header needed for these.
237
-
238
- ### Tool search (non-beta, server-side)
239
-
240
- ```php
241
- tools: [
242
- ['type' => 'tool_search_tool_regex_20251119', 'name' => 'tool_search_tool_regex'],
243
- ['name' => 'get_weather', 'description' => '...', 'inputSchema' => [...], 'deferLoading' => true],
244
- // ... other user tools with 'deferLoading' => true
245
- ],
246
- ```
247
-
248
- ### Memory tool (non-beta, client-executed)
249
-
250
- Declare `['type' => 'memory_20250818', 'name' => 'memory']`. Handle the `tool_use` by reading/writing files under a fixed `/memories` directory. **Validate every model-supplied path**: resolve to its canonical form and verify it remains within the memory directory; reject traversal (`..`, symlinks) - see `shared/tool-use-concepts.md` § Client-Side Tools.
251
-
252
- ---
253
-
@@ -1,443 +0,0 @@
1
- # Managed Agents - PHP
2
-
3
- > **Bindings not shown here:** This README covers the most common managed-agents flows for PHP. If you need a class, method, namespace, field, or behavior that isn't shown, WebFetch the PHP SDK repo **or the relevant docs page** from `shared/live-sources.md` rather than guess. Do not extrapolate from cURL shapes or another language's SDK.
4
-
5
- > **Agents are persistent - create once, reference by ID.** Store the agent ID returned by `$client->beta->agents->create` and pass it to every subsequent `->sessions->create`; do not call `agents->create` in the request path. **Recommended:** define agents and environments as version-controlled YAML applied with the `ant` CLI - see `shared/anthropic-cli.md` (its live-docs URL is in `shared/live-sources.md`). The CLI owns the control plane (create/update); your code owns the data plane (sessions with the stored ID). The examples below show in-code creation for when you must provision programmatically; in production the create call belongs in setup, not in the request path.
6
-
7
- ## Installation
8
-
9
- ```bash
10
- composer require "anthropic-ai/sdk" "guzzlehttp/guzzle:^7"
11
- ```
12
-
13
- ## Client Initialization
14
-
15
- ```php
16
- use Anthropic\Client;
17
-
18
- // Default (uses ANTHROPIC_API_KEY env var)
19
- $client = new Client();
20
-
21
- // Explicit API key
22
- $client = new Client(apiKey: 'your-api-key');
23
- ```
24
-
25
- ---
26
-
27
- ## Create an Environment
28
-
29
- ```php
30
- $environment = $client->beta->environments->create(
31
- name: 'my-dev-env',
32
- config: ['type' => 'cloud', 'networking' => ['type' => 'unrestricted']],
33
- );
34
- echo "Environment ID: {$environment->id}\n"; // env_...
35
- ```
36
-
37
- ---
38
-
39
- ## Create an Agent (required first step)
40
-
41
- > Warning: **There is no inline agent config.** `model`/`system`/`tools` live on the agent object, not the session. Always start with `$client->beta->agents->create()` - the session takes either `agent: $agent->id` or the typed `BetaManagedAgentsAgentParams::with(type: 'agent', id: $agent->id, version: $agent->version)`.
42
-
43
- ### Minimal
44
-
45
- ```php
46
- use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
47
-
48
- // 1. Create the agent (reusable, versioned)
49
- $agent = $client->beta->agents->create(
50
- name: 'Coding Assistant',
51
- model: 'claude-opus-5',
52
- system: 'You are a helpful coding assistant.',
53
- tools: [
54
- BetaManagedAgentsAgentToolset20260401Params::with(
55
- type: 'agent_toolset_20260401',
56
- ),
57
- ],
58
- );
59
-
60
- // 2. Start a session
61
- $session = $client->beta->sessions->create(
62
- agent: ['type' => 'agent', 'id' => $agent->id, 'version' => $agent->version],
63
- environmentID: $environment->id,
64
- title: 'Quickstart session',
65
- );
66
- echo "Session ID: {$session->id}\n";
67
- echo "Trace: https://platform.claude.com/workspaces/default/sessions/{$session->id}\n"; // swap 'default' for your workspace ID if the API key is not in the Default workspace
68
- ```
69
-
70
- ### Updating an Agent
71
-
72
- Updates create new versions; the agent object is immutable per version.
73
-
74
- ```php
75
- $updatedAgent = $client->beta->agents->update(
76
- $agent->id,
77
- version: $agent->version,
78
- system: 'You are a helpful coding agent. Always write tests.',
79
- );
80
- echo "New version: {$updatedAgent->version}\n";
81
-
82
- // List all versions
83
- foreach ($client->beta->agents->versions->list($agent->id)->pagingEachItem() as $version) {
84
- echo "Version {$version->version}: {$version->updatedAt->format(DateTimeInterface::ATOM)}\n";
85
- }
86
-
87
- // Archive the agent
88
- $archived = $client->beta->agents->archive($agent->id);
89
- echo "Archived at: {$archived->archivedAt->format(DateTimeInterface::ATOM)}\n";
90
- ```
91
-
92
- ---
93
-
94
- ## Send a User Message
95
-
96
- ```php
97
- $client->beta->sessions->events->send(
98
- $session->id,
99
- events: [
100
- [
101
- 'type' => 'user.message',
102
- 'content' => [['type' => 'text', 'text' => 'Review the auth module']],
103
- ],
104
- ],
105
- );
106
- ```
107
-
108
- > Tip: **Stream-first:** Open the stream *before* (or concurrently with) sending the message. The stream only delivers events that occur after it opens - stream-after-send means early events arrive buffered in one batch. See [Steering Patterns](../../shared/managed-agents-events.md#steering-patterns).
109
-
110
- ---
111
-
112
- ## Stream Events (SSE)
113
-
114
- > Note: **Streaming transporter:** PHP's default buffered PSR-18 client never returns for the open-ended session event stream. Use a streaming Guzzle transporter for `streamStream()` calls - other calls keep the default client.
115
-
116
- ```php
117
- $streamingClient = new GuzzleHttp\Client(['stream' => true]);
118
-
119
- // Open the stream first, then send the user message
120
- $stream = $client->beta->sessions->events->streamStream(
121
- $session->id,
122
- requestOptions: ['transporter' => $streamingClient],
123
- );
124
- $client->beta->sessions->events->send(
125
- $session->id,
126
- events: [
127
- [
128
- 'type' => 'user.message',
129
- 'content' => [['type' => 'text', 'text' => 'Summarize the repo README']],
130
- ],
131
- ],
132
- );
133
-
134
- foreach ($stream as $event) {
135
- match ($event->type) {
136
- 'agent.message' => array_walk(
137
- $event->content,
138
- static fn($block) => $block->type === 'text' ? print($block->text) : null,
139
- ),
140
- 'agent.tool_use' => print("\n[Using tool: {$event->name}]\n"),
141
- 'session.error' => printf("\n[Error: %s]", $event->error?->message ?? 'unknown'),
142
- default => null,
143
- };
144
- if ($event->type === 'session.status_idle' || $event->type === 'session.error') {
145
- break;
146
- }
147
- }
148
- $stream->close();
149
- ```
150
-
151
- ### Reconnecting and Tailing
152
-
153
- When reconnecting mid-session, list past events first to dedupe, then tail live events:
154
-
155
- ```php
156
- $stream = $client->beta->sessions->events->streamStream(
157
- $session->id,
158
- requestOptions: ['transporter' => $streamingClient],
159
- );
160
-
161
- // Stream is open and buffering. List history before tailing live.
162
- $seenEventIds = [];
163
- foreach ($client->beta->sessions->events->list($session->id)->pagingEachItem() as $event) {
164
- $seenEventIds[$event->id] = true;
165
- }
166
-
167
- // Tail live events, skipping anything already seen
168
- foreach ($stream as $event) {
169
- if (isset($seenEventIds[$event->id])) {
170
- continue;
171
- }
172
- $seenEventIds[$event->id] = true;
173
- match ($event->type) {
174
- 'agent.message' => array_walk(
175
- $event->content,
176
- static fn($block) => $block->type === 'text' ? print($block->text) : null,
177
- ),
178
- default => null,
179
- };
180
- if ($event->type === 'session.status_idle') {
181
- break;
182
- }
183
- }
184
- $stream->close();
185
- ```
186
-
187
- ---
188
-
189
- ## Provide Custom Tool Result
190
-
191
- > Note: The PHP managed-agents bindings for `user.custom_tool_result` are not yet documented in this skill or in the apps source examples. Refer to `shared/managed-agents-events.md` for the wire format and the `anthropic-ai/sdk` PHP repository for the corresponding params.
192
-
193
- ---
194
-
195
- ## Poll Events
196
-
197
- ```php
198
- foreach ($client->beta->sessions->events->list($session->id)->pagingEachItem() as $event) {
199
- echo "{$event->type}: {$event->id}\n";
200
- }
201
- ```
202
-
203
- ---
204
-
205
- ## Upload a File
206
-
207
- > Note: **PHP file upload:** The PHP SDK's beta managed-agents file upload binding is not shown in the apps source examples; the canonical PHP example uses raw cURL against `POST /v1/files`. If your codebase prefers the SDK, WebFetch the `anthropic-ai/sdk` PHP repository for the latest binding before writing code.
208
-
209
- ```php
210
- use Anthropic\Beta\Sessions\BetaManagedAgentsFileResourceParams;
211
-
212
- // Raw cURL upload (canonical example from the apps source)
213
- $csvPath = 'data.csv';
214
- $ch = curl_init('https://api.anthropic.com/v1/files');
215
- curl_setopt_array($ch, [
216
- CURLOPT_RETURNTRANSFER => true,
217
- CURLOPT_POST => true,
218
- CURLOPT_HTTPHEADER => [
219
- 'x-api-key: ' . getenv('ANTHROPIC_API_KEY'),
220
- 'anthropic-version: 2023-06-01',
221
- 'anthropic-beta: files-api-2025-04-14',
222
- ],
223
- CURLOPT_POSTFIELDS => ['file' => new CURLFile($csvPath, 'text/csv', 'data.csv')],
224
- ]);
225
- $file = json_decode(curl_exec($ch));
226
- echo "File ID: {$file->id}\n";
227
-
228
- // Mount in a session
229
- $session = $client->beta->sessions->create(
230
- agent: $agent->id,
231
- environmentID: $environment->id,
232
- resources: [
233
- BetaManagedAgentsFileResourceParams::with(
234
- type: 'file',
235
- fileID: $file->id,
236
- mountPath: '/workspace/data.csv',
237
- ),
238
- ],
239
- );
240
- ```
241
-
242
- ### Add and Manage Resources on an Existing Session
243
-
244
- ```php
245
- // Attach an additional file to an open session
246
- $resource = $client->beta->sessions->resources->add(
247
- $session->id,
248
- type: 'file',
249
- fileID: $file->id,
250
- );
251
- echo "{$resource->id}\n"; // "sesrsc_01ABC..."
252
-
253
- // List resources on the session
254
- $listed = $client->beta->sessions->resources->list($session->id);
255
- foreach ($listed->data as $entry) {
256
- echo "{$entry->id} {$entry->type}\n";
257
- }
258
-
259
- // Detach a resource
260
- $client->beta->sessions->resources->delete($resource->id, sessionID: $session->id);
261
- ```
262
-
263
- ---
264
-
265
- ## List and Download Session Files
266
-
267
- ```php
268
- $files = $client->beta->files->list(
269
- scopeID: 'sesn_abc123',
270
- betas: ['managed-agents-2026-04-01'],
271
- );
272
- $content = $client->beta->files->download($files->data[0]->id);
273
- file_put_contents('output.txt', $content);
274
- ```
275
-
276
- ---
277
-
278
- ## Session Management
279
-
280
- ```php
281
- // List environments
282
- $environments = $client->beta->environments->list();
283
-
284
- // Retrieve a specific environment
285
- $env = $client->beta->environments->retrieve($environment->id);
286
-
287
- // Archive an environment (read-only, existing sessions continue)
288
- $client->beta->environments->archive($environment->id);
289
-
290
- // Delete an environment (only if no sessions reference it)
291
- $client->beta->environments->delete($environment->id);
292
-
293
- // Delete a session
294
- $client->beta->sessions->delete($session->id);
295
- ```
296
-
297
- ---
298
-
299
- ## MCP Server Integration
300
-
301
- ```php
302
- use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
303
- use Anthropic\Beta\Agents\BetaManagedAgentsMCPToolsetParams;
304
- use Anthropic\Beta\Agents\BetaManagedAgentsURLMCPServerParams;
305
- use Anthropic\Beta\Sessions\BetaManagedAgentsAgentParams;
306
-
307
- // Agent declares MCP server (no auth here - auth goes in a vault)
308
- $agent = $client->beta->agents->create(
309
- name: 'GitHub Assistant',
310
- model: 'claude-opus-5',
311
- mcpServers: [
312
- BetaManagedAgentsURLMCPServerParams::with(
313
- type: 'url',
314
- name: 'github',
315
- url: 'https://api.githubcopilot.com/mcp/',
316
- ),
317
- ],
318
- tools: [
319
- BetaManagedAgentsAgentToolset20260401Params::with(type: 'agent_toolset_20260401'),
320
- BetaManagedAgentsMCPToolsetParams::with(
321
- type: 'mcp_toolset',
322
- mcpServerName: 'github',
323
- ),
324
- ],
325
- );
326
-
327
- // Session attaches vault(s) containing credentials for those MCP server URLs
328
- $session = $client->beta->sessions->create(
329
- agent: BetaManagedAgentsAgentParams::with(
330
- type: 'agent',
331
- id: $agent->id,
332
- version: $agent->version,
333
- ),
334
- environmentID: $environment->id,
335
- vaultIDs: [$vault->id],
336
- );
337
- ```
338
-
339
- See `shared/managed-agents-tools.md` §Vaults for creating vaults and adding credentials.
340
-
341
- ---
342
-
343
- ## Vaults
344
-
345
- ```php
346
- // Create a vault
347
- $vault = $client->beta->vaults->create(
348
- displayName: 'Alice',
349
- metadata: ['external_user_id' => 'usr_abc123'],
350
- );
351
- echo $vault->id . "\n"; // "vlt_01ABC..."
352
-
353
- // Add an OAuth credential
354
- $credential = $client->beta->vaults->credentials->create(
355
- vaultID: $vault->id,
356
- displayName: "Alice's Slack",
357
- auth: [
358
- 'type' => 'mcp_oauth',
359
- 'mcp_server_url' => 'https://mcp.slack.com/mcp',
360
- 'access_token' => 'xoxp-...',
361
- 'expires_at' => '2026-04-15T00:00:00Z',
362
- 'refresh' => [
363
- 'token_endpoint' => 'https://slack.com/api/oauth.v2.access',
364
- 'client_id' => '1234567890.0987654321',
365
- 'scope' => 'channels:read chat:write',
366
- 'refresh_token' => 'xoxe-1-...',
367
- 'token_endpoint_auth' => [
368
- 'type' => 'client_secret_post',
369
- 'client_secret' => 'abc123...',
370
- ],
371
- ],
372
- ],
373
- );
374
-
375
- // Rotate the credential (e.g., after a token refresh)
376
- $client->beta->vaults->credentials->update(
377
- $credential->id,
378
- vaultID: $vault->id,
379
- auth: [
380
- 'type' => 'mcp_oauth',
381
- 'access_token' => 'xoxp-new-...',
382
- 'expires_at' => '2026-05-15T00:00:00Z',
383
- 'refresh' => ['refresh_token' => 'xoxe-1-new-...'],
384
- ],
385
- );
386
-
387
- // Archive a vault
388
- $client->beta->vaults->archive($vault->id);
389
- ```
390
-
391
- ---
392
-
393
- ## GitHub Repository Integration
394
-
395
- Mount a GitHub repository as a session resource (a vault holds the GitHub MCP credential):
396
-
397
- ```php
398
- $session = $client->beta->sessions->create(
399
- agent: $agent->id,
400
- environmentID: $environment->id,
401
- vaultIDs: [$vault->id],
402
- resources: [
403
- [
404
- 'type' => 'github_repository',
405
- 'url' => 'https://github.com/org/repo',
406
- 'mount_path' => '/workspace/repo',
407
- 'authorization_token' => 'ghp_your_github_token',
408
- ],
409
- ],
410
- );
411
- ```
412
-
413
- Multiple repositories on the same session:
414
-
415
- ```php
416
- $resources = [
417
- [
418
- 'type' => 'github_repository',
419
- 'url' => 'https://github.com/org/frontend',
420
- 'mount_path' => '/workspace/frontend',
421
- 'authorization_token' => 'ghp_your_github_token',
422
- ],
423
- [
424
- 'type' => 'github_repository',
425
- 'url' => 'https://github.com/org/backend',
426
- 'mount_path' => '/workspace/backend',
427
- 'authorization_token' => 'ghp_your_github_token',
428
- ],
429
- ];
430
- ```
431
-
432
- Rotating a repository's authorization token:
433
-
434
- ```php
435
- $listed = $client->beta->sessions->resources->list($session->id);
436
- $repoResourceId = $listed->data[0]->id;
437
-
438
- $client->beta->sessions->resources->update(
439
- $repoResourceId,
440
- sessionID: $session->id,
441
- authorizationToken: 'ghp_your_new_github_token',
442
- );
443
- ```