@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,335 +0,0 @@
1
- # Managed Agents - Python
2
-
3
- > **Bindings not shown here:** This README covers the most common managed-agents flows for Python. If you need a class, method, namespace, field, or behavior that isn't shown, WebFetch the Python 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 `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
- pip install anthropic
11
- ```
12
-
13
- ## Client Initialization
14
-
15
- ```python
16
- import anthropic
17
-
18
- # Default - resolves credentials from the environment:
19
- # ANTHROPIC_API_KEY, or ANTHROPIC_AUTH_TOKEN, or an `ant auth login` profile.
20
- # Prefer this for local dev; don't hardcode a key.
21
- client = anthropic.Anthropic()
22
-
23
- # Explicit API key (only when you must inject a specific key)
24
- client = anthropic.Anthropic(api_key="your-api-key")
25
- ```
26
-
27
- ---
28
-
29
- ## Create an Environment
30
-
31
- ```python
32
- environment = client.beta.environments.create(
33
- name="my-dev-env",
34
- config={
35
- "type": "cloud",
36
- "networking": {"type": "unrestricted"},
37
- },
38
- )
39
- print(environment.id) # env_...
40
- ```
41
-
42
- ---
43
-
44
- ## Create an Agent (required first step)
45
-
46
- > Warning: **There is no inline agent config.** `model`/`system`/`tools` live on the agent object, not the session. Always start with `agents.create()` - the session only takes `agent={"type": "agent", "id": agent.id}`.
47
-
48
- ### Minimal
49
-
50
- ```python
51
- # 1. Create the agent (reusable, versioned)
52
- agent = client.beta.agents.create(
53
- name="Coding Assistant",
54
- model="claude-opus-5",
55
- tools=[{"type": "agent_toolset_20260401", "default_config": {"enabled": True}}],
56
- )
57
-
58
- # 2. Start a session
59
- session = client.beta.sessions.create(
60
- agent={"type": "agent", "id": agent.id, "version": agent.version},
61
- environment_id=environment.id,
62
- )
63
- print(session.id, session.status)
64
- print(f"Trace: https://platform.claude.com/workspaces/default/sessions/{session.id}") # swap 'default' for your workspace ID if the API key is not in the Default workspace
65
- ```
66
-
67
- ### With system prompt and custom tools
68
-
69
- ```python
70
- import os
71
-
72
- agent = client.beta.agents.create(
73
- name="Code Reviewer",
74
- model="claude-opus-5",
75
- system="You are a senior code reviewer.",
76
- tools=[
77
- {"type": "agent_toolset_20260401"},
78
- {
79
- "type": "custom",
80
- "name": "run_tests",
81
- "description": "Run the test suite",
82
- "input_schema": {
83
- "type": "object",
84
- "properties": {
85
- "test_path": {"type": "string", "description": "Path to test file"}
86
- },
87
- "required": ["test_path"],
88
- },
89
- },
90
- ],
91
- )
92
-
93
- session = client.beta.sessions.create(
94
- agent={"type": "agent", "id": agent.id, "version": agent.version},
95
- environment_id=environment.id,
96
- title="Code review session",
97
- resources=[
98
- {
99
- "type": "github_repository",
100
- "url": "https://github.com/owner/repo",
101
- "mount_path": "/workspace/repo",
102
- "authorization_token": os.environ["GITHUB_TOKEN"],
103
- "branch": "main",
104
- }
105
- ],
106
- )
107
- ```
108
-
109
- ---
110
-
111
- ## Send a User Message
112
-
113
- ```python
114
- client.beta.sessions.events.send(
115
- session_id=session.id,
116
- events=[
117
- {
118
- "type": "user.message",
119
- "content": [{"type": "text", "text": "Review the auth module"}],
120
- }
121
- ],
122
- )
123
- ```
124
-
125
- > 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).
126
-
127
- ---
128
-
129
- ## Stream Events (SSE)
130
-
131
- ```python
132
- import json
133
-
134
- # Stream-first: open stream, then send while stream is live
135
- with client.beta.sessions.events.stream(
136
- session_id=session.id,
137
- ) as stream:
138
- client.beta.sessions.events.send(
139
- session_id=session.id,
140
- events=[{"type": "user.message", "content": [{"type": "text", "text": "..."}]}],
141
- )
142
- for event in stream:
143
- ... # process events
144
-
145
- # Standalone stream iteration:
146
- with client.beta.sessions.events.stream(
147
- session_id=session.id,
148
- ) as stream:
149
- for event in stream:
150
- if event.type == "agent.message":
151
- for block in event.content:
152
- if block.type == "text":
153
- print(block.text, end="", flush=True)
154
- elif event.type == "agent.custom_tool_use":
155
- # Custom tool invocation - session is now idle
156
- print(f"\nCustom tool call: {event.name}")
157
- print(f"Input: {json.dumps(event.input)}")
158
- # Send result back (see below)
159
- elif event.type == "session.status_idle":
160
- print("\n--- Agent idle ---")
161
- elif event.type == "session.status_terminated":
162
- print("\n--- Session terminated ---")
163
- break
164
- ```
165
-
166
- ---
167
-
168
- ## Provide Custom Tool Result
169
-
170
- ```python
171
- client.beta.sessions.events.send(
172
- session_id=session.id,
173
- events=[
174
- {
175
- "type": "user.custom_tool_result",
176
- "custom_tool_use_id": "sevt_abc123",
177
- "content": [{"type": "text", "text": "All 42 tests passed."}],
178
- }
179
- ],
180
- )
181
- ```
182
-
183
- ---
184
-
185
- ## Poll Events
186
-
187
- ```python
188
- events = client.beta.sessions.events.list(
189
- session_id=session.id,
190
- )
191
- for event in events.data:
192
- print(f"{event.type}: {event.id}")
193
- ```
194
-
195
- > Warning: **Prefer the SDK over raw `requests`/`httpx`.** If you hand-roll a poll loop, don't assume `timeout=(5, 60)` or `httpx.Timeout(120)` caps total call duration - both are **per-chunk** read timeouts (reset on every byte), so a trickling response can block forever. For a hard wall-clock deadline, track `time.monotonic()` at the loop level and bail explicitly, or wrap with `asyncio.wait_for()`. See [Receiving Events](../../shared/managed-agents-events.md#receiving-events).
196
-
197
- ---
198
-
199
- ## Full Streaming Loop with Custom Tools
200
-
201
- ```python
202
- import json
203
-
204
-
205
- def run_custom_tool(tool_name: str, tool_input: dict) -> str:
206
- """Execute a custom tool and return the result."""
207
- if tool_name == "run_tests":
208
- # Your tool implementation here
209
- return "All tests passed."
210
- return f"Unknown tool: {tool_name}"
211
-
212
-
213
- def run_session(client, session_id: str):
214
- """Stream events and handle custom tool calls."""
215
- while True:
216
- with client.beta.sessions.events.stream(
217
- session_id=session_id,
218
- ) as stream:
219
- tool_calls = []
220
- for event in stream:
221
- if event.type == "agent.message":
222
- for block in event.content:
223
- if block.type == "text":
224
- print(block.text, end="", flush=True)
225
- elif event.type == "agent.custom_tool_use":
226
- tool_calls.append(event)
227
- elif event.type == "session.status_idle":
228
- break
229
- elif event.type == "session.status_terminated":
230
- return
231
-
232
- if not tool_calls:
233
- break
234
-
235
- # Process custom tool calls
236
- results = []
237
- for call in tool_calls:
238
- result = run_custom_tool(call.name, call.input)
239
- results.append({
240
- "type": "user.custom_tool_result",
241
- "custom_tool_use_id": call.id,
242
- "content": [{"type": "text", "text": result}],
243
- })
244
-
245
- client.beta.sessions.events.send(
246
- session_id=session_id,
247
- events=results,
248
- )
249
- ```
250
-
251
- ---
252
-
253
- ## Upload a File
254
-
255
- ```python
256
- with open("data.csv", "rb") as f:
257
- file = client.beta.files.upload(
258
- file=f,
259
- )
260
-
261
- # Use in a session
262
- session = client.beta.sessions.create(
263
- agent={"type": "agent", "id": agent.id, "version": agent.version},
264
- environment_id=environment.id,
265
- resources=[{"type": "file", "file_id": file.id, "mount_path": "/workspace/data.csv"}],
266
- )
267
- ```
268
-
269
- ---
270
-
271
- ## List and Download Session Files
272
-
273
- List files the agent wrote to `/mnt/session/outputs/` during a session, then download them.
274
-
275
- ```python
276
- # List files associated with a session
277
- files = client.beta.files.list(
278
- scope_id=session.id,
279
- betas=["managed-agents-2026-04-01"],
280
- )
281
- for f in files.data:
282
- print(f.filename, f.size_bytes)
283
- # Download each file and save to disk
284
- file_content = client.beta.files.download(f.id)
285
- file_content.write_to_file(f.filename)
286
- ```
287
-
288
- > Tip: There's a brief indexing lag (~1-3s) between `session.status_idle` and output files appearing in `files.list`. Retry once or twice if the list is empty.
289
-
290
- ---
291
-
292
- ## Session Management
293
-
294
- ```python
295
- # Get session details
296
- session = client.beta.sessions.retrieve(session_id="sesn_011CZxAbc123Def456")
297
- print(session.status, session.usage)
298
-
299
- # List sessions
300
- sessions = client.beta.sessions.list()
301
-
302
- # Delete a session
303
- client.beta.sessions.delete(session_id="sesn_011CZxAbc123Def456")
304
-
305
- # Archive a session
306
- client.beta.sessions.archive(session_id="sesn_011CZxAbc123Def456")
307
- ```
308
-
309
- ---
310
-
311
- ## MCP Server Integration
312
-
313
- ```python
314
- # Agent declares MCP server (no auth here - auth goes in a vault)
315
- agent = client.beta.agents.create(
316
- name="MCP Agent",
317
- model="claude-opus-5",
318
- mcp_servers=[
319
- {"type": "url", "name": "my-tools", "url": "https://my-mcp-server.example.com/sse"},
320
- ],
321
- tools=[
322
- {"type": "agent_toolset_20260401", "default_config": {"enabled": True}},
323
- {"type": "mcp_toolset", "mcp_server_name": "my-tools"},
324
- ],
325
- )
326
-
327
- # Session attaches vault(s) containing credentials for those MCP server URLs
328
- session = client.beta.sessions.create(
329
- agent=agent.id,
330
- environment_id=environment.id,
331
- vault_ids=[vault.id],
332
- )
333
- ```
334
-
335
- See `shared/managed-agents-tools.md` §Vaults for creating vaults and adding credentials.
@@ -1,134 +0,0 @@
1
- # Claude API - Ruby
2
-
3
- > **Note:** The Ruby SDK supports the Claude API. A tool runner is available in beta via `client.beta.messages.tool_runner()`. Agent SDK is not yet available for Ruby.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- gem install anthropic
9
- ```
10
-
11
- ## Client Initialization
12
-
13
- ```ruby
14
- require "anthropic"
15
-
16
- # Default (uses ANTHROPIC_API_KEY env var)
17
- client = Anthropic::Client.new
18
-
19
- # Explicit API key
20
- client = Anthropic::Client.new(api_key: "your-api-key")
21
- ```
22
-
23
- ---
24
-
25
- ## Basic Message Request
26
-
27
- ```ruby
28
- message = client.messages.create(
29
- model: :"claude-opus-5",
30
- max_tokens: 16000,
31
- messages: [
32
- { role: "user", content: "What is the capital of France?" }
33
- ]
34
- )
35
- # content is an array of polymorphic block objects (TextBlock, ThinkingBlock,
36
- # ToolUseBlock, ...). .type is a Symbol - compare with :text, not "text".
37
- # .text raises NoMethodError on non-TextBlock entries.
38
- message.content.each do |block|
39
- puts block.text if block.type == :text
40
- end
41
- ```
42
-
43
- ---
44
-
45
- ## Extended Thinking
46
-
47
- > **Fable 5, Claude Opus 5, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking. `budget_tokens` is removed on Fable 5, Claude Opus 5, Opus 4.8, and 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6.
48
- > **Claude Opus 5:** thinking is on by default - omitting `thinking:` runs adaptive (`{ type: "adaptive" }` is equivalent), unlike Opus 4.8/4.7 where omitting it meant no thinking. `{ type: "disabled" }` is accepted only at effort `high` or lower; pairing it with `xhigh`/`max` returns a 400.
49
- > **Older models:** Use `thinking: { type: "enabled", budget_tokens: N }` (must be < `max_tokens`, min 1024).
50
-
51
- ```ruby
52
- message = client.messages.create(
53
- model: :"claude-opus-5",
54
- max_tokens: 16000,
55
- thinking: { type: "adaptive" },
56
- messages: [{ role: "user", content: "Solve: 27 * 453" }]
57
- )
58
-
59
- message.content.each do |block|
60
- case block.type
61
- when :thinking then puts "Thinking: #{block.thinking}"
62
- when :text then puts "Response: #{block.text}"
63
- end
64
- end
65
- ```
66
-
67
- ---
68
-
69
- ## Prompt Caching
70
-
71
- `system_:` (trailing underscore - avoids shadowing `Kernel#system`) takes an array of text blocks; set `cache_control` on the last block. Plain hashes work via the `OrHash` type alias. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.
72
-
73
- ```ruby
74
- message = client.messages.create(
75
- model: :"claude-opus-5",
76
- max_tokens: 16000,
77
- system_: [
78
- { type: "text", text: long_system_prompt, cache_control: { type: "ephemeral" } }
79
- ],
80
- messages: [{ role: "user", content: "Summarize the key points" }]
81
- )
82
- ```
83
-
84
- For 1-hour TTL: `cache_control: { type: "ephemeral", ttl: "1h" }`. There's also a top-level `cache_control:` on `messages.create` that auto-places on the last cacheable block.
85
-
86
- Verify hits via `message.usage.cache_creation_input_tokens` / `message.usage.cache_read_input_tokens`.
87
-
88
- ---
89
-
90
- ## Stop Details
91
-
92
- When `stop_reason` is `:refusal`, the response includes structured `stop_details`:
93
-
94
- ```ruby
95
- if message.stop_reason == :refusal && message.stop_details
96
- puts "Category: #{message.stop_details.category}" # e.g. :cyber, :bio, :reasoning_extraction, :frontier_llm, or nil - see docs for the full set
97
- puts "Explanation: #{message.stop_details.explanation}"
98
- end
99
- ```
100
-
101
- **Refusal fallbacks (Claude Fable 5.1) - opt in by default.** Fallbacks are opt-in: without them a refused request simply stops. New `claude-fable-5-1` code should include the server-side `fallbacks` parameter (beta header `server-side-fallback-2026-06-01`, `fallbacks: [{model: "claude-opus-4-8"}]` on the beta messages call) by default. The exact Ruby binding (and the client-side middleware for providers without server-side support) is not documented here - WebFetch the Ruby SDK repo's `examples/` from `shared/live-sources.md`; full semantics in `shared/model-migration.md` -> Migrating to Claude Fable 5.1 -> `refusal` stop reason.
102
-
103
- ---
104
-
105
- ## Beta Features
106
-
107
- `betas:` is only valid on `client.beta.messages.create`, not the non-beta path.
108
-
109
- ### Task budgets
110
-
111
- ```ruby
112
- response = client.beta.messages.create(
113
- model: :"claude-opus-5",
114
- max_tokens: 16000,
115
- output_config: { task_budget: { type: :tokens, total: 64_000 } },
116
- tools: [...],
117
- messages: [...],
118
- betas: ["task-budgets-2026-03-13"]
119
- )
120
- ```
121
-
122
- ---
123
-
124
- ## Error Type
125
-
126
- `APIStatusError` exposes a `.type` field for programmatic error classification:
127
-
128
- ```ruby
129
- begin
130
- client.messages.create(...)
131
- rescue Anthropic::Errors::APIStatusError => e
132
- puts e.type # :rate_limit_error, :overloaded_error, etc.
133
- end
134
- ```
@@ -1,16 +0,0 @@
1
- # Streaming - Ruby
2
-
3
- ## Streaming
4
-
5
- ```ruby
6
- stream = client.messages.stream(
7
- model: :"claude-opus-5",
8
- max_tokens: 64000,
9
- messages: [{ role: "user", content: "Write a haiku" }]
10
- )
11
-
12
- stream.text.each { |text| print(text) }
13
- ```
14
-
15
- ---
16
-
@@ -1,41 +0,0 @@
1
- # Tool Use - Ruby
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
- The Ruby SDK supports tool use via raw JSON schema definitions and also provides a beta tool runner for automatic tool execution.
8
-
9
- ### Tool Runner (Beta)
10
-
11
- ```ruby
12
- class GetWeatherInput < Anthropic::BaseModel
13
- required :location, String, doc: "City and state, e.g. San Francisco, CA"
14
- end
15
-
16
- class GetWeather < Anthropic::BaseTool
17
- doc "Get the current weather for a location"
18
-
19
- input_schema GetWeatherInput
20
-
21
- def call(input)
22
- "The weather in #{input.location} is sunny and 72°F."
23
- end
24
- end
25
-
26
- client.beta.messages.tool_runner(
27
- model: :"claude-opus-5",
28
- max_tokens: 16000,
29
- tools: [GetWeather.new],
30
- messages: [{ role: "user", content: "What's the weather in San Francisco?" }]
31
- ).each_message do |message|
32
- puts message.content
33
- end
34
- ```
35
-
36
- ### Manual Loop
37
-
38
- See the [shared tool use concepts](../../shared/tool-use-concepts.md) for the tool definition format and agentic loop pattern.
39
-
40
- ---
41
-