@preapexis/piexis 0.1.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 (154) hide show
  1. package/.github/workflows/publish.yml +35 -0
  2. package/AGENTS.md +21 -41
  3. package/README.md +75 -142
  4. package/extensions/agents.ts +205 -0
  5. package/extensions/ask-question.ts +54 -95
  6. package/extensions/recommended-tools.ts +62 -0
  7. package/extensions/ui.ts +204 -58
  8. package/lib/agent-config.ts +55 -0
  9. package/lib/agents.ts +208 -0
  10. package/lib/question-model.ts +98 -0
  11. package/lib/question-ui.ts +214 -0
  12. package/lib/recommended-tools.ts +119 -0
  13. package/lib/subagent-runner.ts +146 -0
  14. package/lib/ui-tips.json +41 -0
  15. package/package.json +9 -12
  16. package/prompts/init.md +10 -2
  17. package/prompts/summary.md +7 -6
  18. package/schemas/agent.schema.json +48 -0
  19. package/scripts/release.mjs +32 -0
  20. package/skills/{claude-api/LICENSE.txt → caveman/LICENSE} +2 -2
  21. package/skills/caveman/LICENSE-MIT +21 -0
  22. package/skills/caveman/NOTICE +10 -0
  23. package/skills/caveman/SKILL.md +89 -0
  24. package/skills/find-skills/SKILL.md +141 -0
  25. package/skills/ponytail/LICENSE +21 -0
  26. package/skills/ponytail/NOTICE +9 -0
  27. package/skills/ponytail/SKILL.md +52 -0
  28. package/skills-lock.json +6 -0
  29. package/tests/agents.test.mjs +605 -0
  30. package/tests/ask-question-pty.test.mjs +16 -0
  31. package/tests/ask-question.test.mjs +269 -0
  32. package/tests/fixtures/agents-provider.ts +55 -0
  33. package/tests/fixtures/ask-question-pty.py +91 -0
  34. package/tests/fixtures/ask-question-terminal.mjs +69 -0
  35. package/tests/fixtures/recommended-tools-terminal.mjs +103 -0
  36. package/tests/init-workflow.test.mjs +31 -0
  37. package/tests/recommended-tools-pty.test.mjs +16 -0
  38. package/tests/recommended-tools.test.mjs +423 -0
  39. package/tests/resources.test.mjs +66 -0
  40. package/tests/skills-routing.test.mjs +7 -4
  41. package/tests/ui-tip-reload.test.mjs +70 -0
  42. package/tests/ui.test.mjs +450 -0
  43. package/tsconfig.json +1 -0
  44. package/.github/workflows/npm-publish.yml +0 -63
  45. package/PERMISSION_MODES_PLAN.md +0 -279
  46. package/WHAT_YOU_GET.md +0 -153
  47. package/eval/README.md +0 -72
  48. package/eval/permission-cases.json +0 -28
  49. package/eval/permissions.mjs +0 -103
  50. package/extensions/background-tasks.ts +0 -433
  51. package/extensions/background-worker.ts +0 -50
  52. package/extensions/glob.ts +0 -32
  53. package/extensions/mode.ts +0 -397
  54. package/lib/bash-approvals.ts +0 -113
  55. package/lib/bash-policy.ts +0 -164
  56. package/lib/mode-policy.ts +0 -174
  57. package/lib/path-policy.ts +0 -182
  58. package/lib/permission-classifier.ts +0 -128
  59. package/lib/permission-config.ts +0 -91
  60. package/lib/permission-denials.ts +0 -32
  61. package/lib/permission-intent.ts +0 -128
  62. package/lib/permission-taxonomy.ts +0 -15
  63. package/lib/task-broker.ts +0 -65
  64. package/lib/task-checkout.ts +0 -39
  65. package/lib/task-git.ts +0 -44
  66. package/lib/task-patch.ts +0 -106
  67. package/lib/task-permissions.ts +0 -51
  68. package/lib/task-report.ts +0 -62
  69. package/lib/task-worktree-policy.ts +0 -56
  70. package/skills/claude-api/SKILL.md +0 -572
  71. package/skills/claude-api/csharp/claude-api/README.md +0 -362
  72. package/skills/claude-api/csharp/claude-api/batches.md +0 -14
  73. package/skills/claude-api/csharp/claude-api/files-api.md +0 -25
  74. package/skills/claude-api/csharp/claude-api/streaming.md +0 -28
  75. package/skills/claude-api/csharp/claude-api/tool-use.md +0 -164
  76. package/skills/claude-api/curl/examples.md +0 -256
  77. package/skills/claude-api/curl/managed-agents.md +0 -371
  78. package/skills/claude-api/go/claude-api/README.md +0 -188
  79. package/skills/claude-api/go/claude-api/files-api.md +0 -23
  80. package/skills/claude-api/go/claude-api/streaming.md +0 -43
  81. package/skills/claude-api/go/claude-api/tool-use.md +0 -220
  82. package/skills/claude-api/go/managed-agents/README.md +0 -564
  83. package/skills/claude-api/java/claude-api/README.md +0 -238
  84. package/skills/claude-api/java/claude-api/files-api.md +0 -27
  85. package/skills/claude-api/java/claude-api/streaming.md +0 -24
  86. package/skills/claude-api/java/claude-api/tool-use.md +0 -228
  87. package/skills/claude-api/java/managed-agents/README.md +0 -443
  88. package/skills/claude-api/php/claude-api/README.md +0 -174
  89. package/skills/claude-api/php/claude-api/batches.md +0 -15
  90. package/skills/claude-api/php/claude-api/files-api.md +0 -13
  91. package/skills/claude-api/php/claude-api/streaming.md +0 -27
  92. package/skills/claude-api/php/claude-api/tool-use.md +0 -253
  93. package/skills/claude-api/php/managed-agents/README.md +0 -443
  94. package/skills/claude-api/python/claude-api/README.md +0 -565
  95. package/skills/claude-api/python/claude-api/batches.md +0 -198
  96. package/skills/claude-api/python/claude-api/files-api.md +0 -170
  97. package/skills/claude-api/python/claude-api/sdk-upgrade.md +0 -286
  98. package/skills/claude-api/python/claude-api/streaming.md +0 -179
  99. package/skills/claude-api/python/claude-api/tool-use.md +0 -627
  100. package/skills/claude-api/python/managed-agents/README.md +0 -335
  101. package/skills/claude-api/ruby/claude-api/README.md +0 -134
  102. package/skills/claude-api/ruby/claude-api/streaming.md +0 -16
  103. package/skills/claude-api/ruby/claude-api/tool-use.md +0 -41
  104. package/skills/claude-api/ruby/managed-agents/README.md +0 -394
  105. package/skills/claude-api/shared/admin-api.md +0 -179
  106. package/skills/claude-api/shared/agent-design.md +0 -101
  107. package/skills/claude-api/shared/anthropic-cli.md +0 -269
  108. package/skills/claude-api/shared/claude-platform-on-aws.md +0 -59
  109. package/skills/claude-api/shared/cost-optimization.md +0 -233
  110. package/skills/claude-api/shared/error-codes.md +0 -262
  111. package/skills/claude-api/shared/live-sources.md +0 -166
  112. package/skills/claude-api/shared/managed-agents-api-reference.md +0 -455
  113. package/skills/claude-api/shared/managed-agents-client-patterns.md +0 -220
  114. package/skills/claude-api/shared/managed-agents-core.md +0 -359
  115. package/skills/claude-api/shared/managed-agents-environments.md +0 -226
  116. package/skills/claude-api/shared/managed-agents-events.md +0 -290
  117. package/skills/claude-api/shared/managed-agents-memory.md +0 -201
  118. package/skills/claude-api/shared/managed-agents-multiagent.md +0 -260
  119. package/skills/claude-api/shared/managed-agents-onboarding.md +0 -82
  120. package/skills/claude-api/shared/managed-agents-outcomes.md +0 -108
  121. package/skills/claude-api/shared/managed-agents-overview.md +0 -77
  122. package/skills/claude-api/shared/managed-agents-scheduled-deployments.md +0 -156
  123. package/skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +0 -282
  124. package/skills/claude-api/shared/managed-agents-tools.md +0 -504
  125. package/skills/claude-api/shared/managed-agents-webhooks.md +0 -143
  126. package/skills/claude-api/shared/model-migration.md +0 -1872
  127. package/skills/claude-api/shared/models.md +0 -142
  128. package/skills/claude-api/shared/platform-availability.md +0 -53
  129. package/skills/claude-api/shared/prompt-audit.md +0 -223
  130. package/skills/claude-api/shared/prompt-caching.md +0 -292
  131. package/skills/claude-api/shared/token-counting.md +0 -56
  132. package/skills/claude-api/shared/tool-use-concepts.md +0 -526
  133. package/skills/claude-api/typescript/claude-api/README.md +0 -405
  134. package/skills/claude-api/typescript/claude-api/batches.md +0 -106
  135. package/skills/claude-api/typescript/claude-api/files-api.md +0 -98
  136. package/skills/claude-api/typescript/claude-api/streaming.md +0 -178
  137. package/skills/claude-api/typescript/claude-api/tool-use.md +0 -586
  138. package/skills/claude-api/typescript/managed-agents/README.md +0 -359
  139. package/tests/auto-permissions.test.mjs +0 -315
  140. package/tests/background-tasks.test.mjs +0 -27
  141. package/tests/background-worker.test.mjs +0 -60
  142. package/tests/bash-permissions.test.mjs +0 -276
  143. package/tests/glob.test.mjs +0 -31
  144. package/tests/mode.test.mjs +0 -62
  145. package/tests/permission-evaluation.test.mjs +0 -70
  146. package/tests/permission-foundation.test.mjs +0 -194
  147. package/tests/permission-policy.test.mjs +0 -158
  148. package/tests/runtime/README.md +0 -51
  149. package/tests/runtime/harness.mjs +0 -190
  150. package/tests/runtime/permissions.test.mjs +0 -192
  151. package/tests/runtime/tui.test.mjs +0 -60
  152. package/tests/task-integration.test.mjs +0 -324
  153. package/tests/task-permissions.test.mjs +0 -178
  154. package/tests/task-worktree-policy.test.mjs +0 -53
@@ -1,188 +0,0 @@
1
- # Claude API - Go
2
-
3
- > **Note:** The Go SDK supports the Claude API and beta tool use with `BetaToolRunner`. Agent SDK is not yet available for Go.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- go get github.com/anthropics/anthropic-sdk-go
9
- ```
10
-
11
- ## Client Initialization
12
-
13
- ```go
14
- import (
15
- "github.com/anthropics/anthropic-sdk-go"
16
- "github.com/anthropics/anthropic-sdk-go/option"
17
- )
18
-
19
- // Default (uses ANTHROPIC_API_KEY env var)
20
- client := anthropic.NewClient()
21
-
22
- // Explicit API key
23
- client := anthropic.NewClient(
24
- option.WithAPIKey("your-api-key"),
25
- )
26
- ```
27
-
28
- ---
29
-
30
- ## Model Constants
31
-
32
- The Go SDK provides typed model constants: `anthropic.ModelClaudeFable5`, `anthropic.ModelClaudeOpus4_8`, `anthropic.ModelClaudeOpus4_7`, `anthropic.ModelClaudeSonnet4_6`, `anthropic.ModelClaudeHaiku4_5_20251001`. Default to Claude Opus 5 unless the user specifies otherwise; if they ask for Fable or the most powerful model, use `anthropic.ModelClaudeFable5` (see `shared/models.md` for the full resolution table).
33
-
34
- `anthropic.Model` is an alias for `string`, so a model with no typed constant yet - including Claude Opus 5 - is passed as the plain id: `Model: "claude-opus-5"`. Check the SDK release notes for a typed `Claude Opus 5` constant before assuming one exists.
35
-
36
- ---
37
-
38
- ## Basic Message Request
39
-
40
- ```go
41
- response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
42
- Model: "claude-opus-5",
43
- MaxTokens: 16000,
44
- Messages: []anthropic.MessageParam{
45
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is the capital of France?")),
46
- },
47
- })
48
- if err != nil {
49
- log.Fatal(err)
50
- }
51
- for _, block := range response.Content {
52
- switch variant := block.AsAny().(type) {
53
- case anthropic.TextBlock:
54
- fmt.Println(variant.Text)
55
- }
56
- }
57
- ```
58
-
59
- ---
60
-
61
- ## Thinking
62
-
63
- Enable Claude's internal reasoning by setting `Thinking` in `MessageNewParams`. The response will contain `ThinkingBlock` content before the final `TextBlock`.
64
-
65
- **Adaptive thinking is the recommended mode for Claude 4.6+ models.** Claude decides dynamically when and how much to think. Combine with the `effort` parameter for cost-quality control.
66
-
67
- Derived from `anthropic-sdk-go/message.go` (`ThinkingConfigParamUnion`, `ThinkingConfigAdaptiveParam`).
68
-
69
- ```go
70
- // There is no ThinkingConfigParamOfAdaptive helper - construct the union
71
- // struct-literal directly and take the address of the variant.
72
- adaptive := anthropic.ThinkingConfigAdaptiveParam{}
73
- params := anthropic.MessageNewParams{
74
- Model: anthropic.ModelClaudeSonnet4_6,
75
- MaxTokens: 16000,
76
- Thinking: anthropic.ThinkingConfigParamUnion{OfAdaptive: &adaptive},
77
- Messages: []anthropic.MessageParam{
78
- anthropic.NewUserMessage(anthropic.NewTextBlock("How many r's in strawberry?")),
79
- },
80
- }
81
-
82
- resp, err := client.Messages.New(context.Background(), params)
83
- if err != nil {
84
- log.Fatal(err)
85
- }
86
-
87
- // ThinkingBlock(s) precede TextBlock in content
88
- for _, block := range resp.Content {
89
- switch b := block.AsAny().(type) {
90
- case anthropic.ThinkingBlock:
91
- fmt.Println("[thinking]", b.Thinking)
92
- case anthropic.TextBlock:
93
- fmt.Println(b.Text)
94
- }
95
- }
96
- ```
97
-
98
- > **Fable 5, Claude Opus 5, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking (above). `ThinkingConfigParamOfEnabled(budgetTokens)` 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.
99
- > **Claude Opus 5:** thinking is on by default - leaving `Thinking` unset runs adaptive (the adaptive union is equivalent), unlike Opus 4.8/4.7 where leaving it unset meant no thinking.
100
- > **Older models:** Use `anthropic.ThinkingConfigParamOfEnabled(N)` (budget must be < `MaxTokens`, min 1024).
101
-
102
- To disable: `anthropic.ThinkingConfigParamUnion{OfDisabled: &anthropic.ThinkingConfigDisabledParam{}}`. On Claude Opus 5 that is accepted only at effort `high` or lower - pairing it with `xhigh`/`max` returns a 400.
103
-
104
- ---
105
-
106
- ## Prompt Caching
107
-
108
- `System` is `[]TextBlockParam`; set `CacheControl` on the last block to cache tools + system together. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.
109
-
110
- ```go
111
- System: []anthropic.TextBlockParam{{
112
- Text: longSystemPrompt,
113
- CacheControl: anthropic.NewCacheControlEphemeralParam(), // default 5m TTL
114
- }},
115
- ```
116
-
117
- For 1-hour TTL: `anthropic.CacheControlEphemeralParam{TTL: anthropic.CacheControlEphemeralTTLTTL1h}`. There's also a top-level `CacheControl` on `MessageNewParams` that auto-places on the last cacheable block.
118
-
119
- Verify hits via `resp.Usage.CacheCreationInputTokens` / `resp.Usage.CacheReadInputTokens`.
120
-
121
- ---
122
-
123
- ## Stop Details
124
-
125
- When `StopReason` is `anthropic.StopReasonRefusal`, the response includes structured `StopDetails`:
126
-
127
- ```go
128
- if resp.StopReason == anthropic.StopReasonRefusal {
129
- fmt.Println("Category:", resp.StopDetails.Category) // e.g. "cyber", "bio", "reasoning_extraction", "frontier_llm", or "" - see docs for the full set
130
- fmt.Println("Explanation:", resp.StopDetails.Explanation)
131
- }
132
- ```
133
-
134
- **Refusal fallbacks (Claude Fable 5.1) - opt in by default.** Fallbacks are opt-in: without them a refused request simply stops. In `claude-fable-5-1` code, include `Fallbacks: []anthropic.BetaFallbackParam{{Model: "claude-opus-4-8"}}` plus the `anthropic.AnthropicBetaServerSideFallback2026_06_01` beta on `client.Beta.Messages.New` by default - a policy decline is re-served by the fallback model inside the same call. Not available on Amazon Bedrock, Vertex AI, or Microsoft Foundry - register the client-side middleware there: `option.WithMiddleware(betafallback.BetaRefusalFallbackMiddleware(...))` from `lib/betafallback`, with per-conversation state via `betafallback.WithBetaFallbackState(&betafallback.BetaFallbackState{})`. Full semantics (billing, sticky routing, streaming) and a runnable example: `shared/model-migration.md` -> Migrating to Claude Fable 5.1 -> `refusal` stop reason, and the Go SDK repo's `examples/` (WebFetch via `shared/live-sources.md`).
135
-
136
- ---
137
-
138
- ## PDF / Document Input
139
-
140
- `NewDocumentBlock` generic helper accepts any source type. `MediaType`/`Type` are auto-set.
141
-
142
- ```go
143
- b64 := base64.StdEncoding.EncodeToString(pdfBytes)
144
-
145
- msg := anthropic.NewUserMessage(
146
- anthropic.NewDocumentBlock(anthropic.Base64PDFSourceParam{Data: b64}),
147
- anthropic.NewTextBlock("Summarize this document"),
148
- )
149
- ```
150
-
151
- Other sources: `URLPDFSourceParam{URL: "https://..."}`, `PlainTextSourceParam{Data: "..."}`.
152
-
153
- ---
154
-
155
- ## Context Editing / Compaction (Beta)
156
-
157
- Use `Beta.Messages.New` with `ContextManagement` on `BetaMessageNewParams`. There is no `NewBetaAssistantMessage` - use `.ToParam()` for the round-trip.
158
-
159
- ```go
160
- params := anthropic.BetaMessageNewParams{
161
- Model: "claude-opus-5", // also supported: ModelClaudeOpus4_8, ModelClaudeSonnet4_6
162
- MaxTokens: 16000,
163
- Betas: []anthropic.AnthropicBeta{"compact-2026-01-12"},
164
- ContextManagement: anthropic.BetaContextManagementConfigParam{
165
- Edits: []anthropic.BetaContextManagementConfigEditUnionParam{
166
- {OfCompact20260112: &anthropic.BetaCompact20260112EditParam{}},
167
- },
168
- },
169
- Messages: []anthropic.BetaMessageParam{ /* ... */ },
170
- }
171
-
172
- resp, err := client.Beta.Messages.New(ctx, params)
173
- if err != nil {
174
- log.Fatal(err)
175
- }
176
-
177
- // Round-trip: append response to history via .ToParam()
178
- params.Messages = append(params.Messages, resp.ToParam())
179
-
180
- // Read compaction blocks from the response
181
- for _, block := range resp.Content {
182
- if c, ok := block.AsAny().(anthropic.BetaCompactionBlock); ok {
183
- fmt.Println("compaction summary:", c.Content)
184
- }
185
- }
186
- ```
187
-
188
- Other edit types: `BetaClearToolUses20250919EditParam`, `BetaClearThinking20251015EditParam` - these need `Betas: []anthropic.AnthropicBeta{"context-management-2025-06-27"}`, not `compact-2026-01-12`.
@@ -1,23 +0,0 @@
1
- # Files API - Go
2
-
3
- ## Files API
4
-
5
- > **Out of beta.** In current SDKs `client.Beta.Files` has breaking shape changes from previous versions, matching the stable `client.Files` - migrate per the Files API row in `shared/live-sources.md`. Examples below predate this.
6
-
7
- Under `client.Beta.Files`. Method is **`Upload`** (NOT `New`/`Create`), params struct is `BetaFileUploadParams`. The `File` field takes an `io.Reader`; use `anthropic.File()` to attach a filename + content-type for the multipart encoding.
8
-
9
- ```go
10
- f, _ := os.Open("./upload_me.txt")
11
- defer f.Close()
12
-
13
- meta, err := client.Beta.Files.Upload(ctx, anthropic.BetaFileUploadParams{
14
- File: anthropic.File(f, "upload_me.txt", "text/plain"),
15
- Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
16
- })
17
- // meta.ID is the file_id to reference in subsequent message requests
18
- ```
19
-
20
- Other `Beta.Files` methods: `List`, `Delete`, `Download`, `GetMetadata`.
21
-
22
- ---
23
-
@@ -1,43 +0,0 @@
1
- # Streaming - Go
2
-
3
- ## Streaming
4
-
5
- ```go
6
- stream := client.Messages.NewStreaming(context.Background(), anthropic.MessageNewParams{
7
- Model: anthropic.ModelClaudeOpus4_8,
8
- MaxTokens: 64000,
9
- Messages: []anthropic.MessageParam{
10
- anthropic.NewUserMessage(anthropic.NewTextBlock("Write a haiku")),
11
- },
12
- })
13
-
14
- for stream.Next() {
15
- event := stream.Current()
16
- switch eventVariant := event.AsAny().(type) {
17
- case anthropic.ContentBlockDeltaEvent:
18
- switch deltaVariant := eventVariant.Delta.AsAny().(type) {
19
- case anthropic.TextDelta:
20
- fmt.Print(deltaVariant.Text)
21
- }
22
- }
23
- }
24
- if err := stream.Err(); err != nil {
25
- log.Fatal(err)
26
- }
27
- ```
28
-
29
- **Accumulating the final message** (there is no `GetFinalMessage()` on the stream):
30
-
31
- ```go
32
- stream := client.Messages.NewStreaming(ctx, params)
33
- message := anthropic.Message{}
34
- for stream.Next() {
35
- message.Accumulate(stream.Current())
36
- }
37
- if err := stream.Err(); err != nil { log.Fatal(err) }
38
- // message.Content now has the complete response
39
- ```
40
-
41
-
42
- ---
43
-
@@ -1,220 +0,0 @@
1
- # Tool Use - Go
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 - Recommended)
8
-
9
- **Beta:** The Go SDK provides `BetaToolRunner` for automatic tool use loops via the `toolrunner` package.
10
-
11
- ```go
12
- import (
13
- "context"
14
- "fmt"
15
- "log"
16
-
17
- "github.com/anthropics/anthropic-sdk-go"
18
- "github.com/anthropics/anthropic-sdk-go/toolrunner"
19
- )
20
-
21
- // Define tool input with jsonschema tags for automatic schema generation
22
- type GetWeatherInput struct {
23
- City string `json:"city" jsonschema:"required,description=The city name"`
24
- }
25
-
26
- // Create a tool with automatic schema generation from struct tags
27
- weatherTool, err := toolrunner.NewBetaToolFromJSONSchema(
28
- "get_weather",
29
- "Get current weather for a city",
30
- func(ctx context.Context, input GetWeatherInput) (anthropic.BetaToolResultBlockParamContentUnion, error) {
31
- return anthropic.BetaToolResultBlockParamContentUnion{
32
- OfText: &anthropic.BetaTextBlockParam{
33
- Text: fmt.Sprintf("The weather in %s is sunny, 72°F", input.City),
34
- },
35
- }, nil
36
- },
37
- )
38
- if err != nil {
39
- log.Fatal(err)
40
- }
41
-
42
- // Create a tool runner that handles the conversation loop automatically
43
- runner := client.Beta.Messages.NewToolRunner(
44
- []anthropic.BetaTool{weatherTool},
45
- anthropic.BetaToolRunnerParams{
46
- BetaMessageNewParams: anthropic.BetaMessageNewParams{
47
- Model: anthropic.ModelClaudeOpus4_8,
48
- MaxTokens: 16000,
49
- Messages: []anthropic.BetaMessageParam{
50
- anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's the weather in Paris?")),
51
- },
52
- },
53
- MaxIterations: 5,
54
- },
55
- )
56
-
57
- // Run until Claude produces a final response
58
- message, err := runner.RunToCompletion(context.Background())
59
- if err != nil {
60
- log.Fatal(err)
61
- }
62
-
63
- // RunToCompletion returns *BetaMessage; content is []BetaContentBlockUnion.
64
- // Narrow via AsAny() switch - note the Beta-namespace types (BetaTextBlock,
65
- // not TextBlock):
66
- for _, block := range message.Content {
67
- switch block := block.AsAny().(type) {
68
- case anthropic.BetaTextBlock:
69
- fmt.Println(block.Text)
70
- }
71
- }
72
- ```
73
-
74
- **Key features of the Go tool runner:**
75
-
76
- - Automatic schema generation from Go structs via `jsonschema` tags
77
- - `RunToCompletion()` for simple one-shot usage
78
- - `All()` iterator for processing each message in the conversation
79
- - `NextMessage()` for step-by-step iteration
80
- - Streaming variant via `NewToolRunnerStreaming()` with `AllStreaming()`
81
-
82
- ### Manual Loop
83
-
84
- Prefer the tool runner above. For interception, validation, logging, or human-in-the-loop approval, gate inside the tool's run function or step the runner with `NextMessage()`/`All()` and inspect each message (the runner's public `Params` field lets you adjust the next request) - a manual loop is not required. Drop to a manual loop only when you need control the runner does not expose: define tools with `ToolParam`, check `StopReason`, execute tools yourself, and feed `tool_result` blocks back.
85
-
86
- Derived from `anthropic-sdk-go/examples/tools/main.go`.
87
-
88
- ```go
89
- package main
90
-
91
- import (
92
- "context"
93
- "encoding/json"
94
- "fmt"
95
- "log"
96
-
97
- "github.com/anthropics/anthropic-sdk-go"
98
- )
99
-
100
- func main() {
101
- client := anthropic.NewClient()
102
-
103
- // 1. Define tools. ToolParam.InputSchema uses a map, no struct tags needed.
104
- addTool := anthropic.ToolParam{
105
- Name: "add",
106
- Description: anthropic.String("Add two integers"),
107
- InputSchema: anthropic.ToolInputSchemaParam{
108
- Properties: map[string]any{
109
- "a": map[string]any{"type": "integer"},
110
- "b": map[string]any{"type": "integer"},
111
- },
112
- },
113
- }
114
- // ToolParam must be wrapped in ToolUnionParam for the Tools slice
115
- tools := []anthropic.ToolUnionParam{{OfTool: &addTool}}
116
-
117
- messages := []anthropic.MessageParam{
118
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is 2 + 3?")),
119
- }
120
-
121
- for {
122
- resp, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
123
- Model: anthropic.ModelClaudeSonnet4_6,
124
- MaxTokens: 16000,
125
- Messages: messages,
126
- Tools: tools,
127
- })
128
- if err != nil {
129
- log.Fatal(err)
130
- }
131
-
132
- // 2. Append the assistant response to history BEFORE processing tool calls.
133
- // resp.ToParam() converts Message -> MessageParam in one call.
134
- messages = append(messages, resp.ToParam())
135
-
136
- // 3. Walk content blocks. ContentBlockUnion is a flattened struct;
137
- // use block.AsAny().(type) to switch on the actual variant.
138
- toolResults := []anthropic.ContentBlockParamUnion{}
139
- for _, block := range resp.Content {
140
- switch variant := block.AsAny().(type) {
141
- case anthropic.TextBlock:
142
- fmt.Println(variant.Text)
143
- case anthropic.ToolUseBlock:
144
- // 4. Parse the tool input. Use variant.JSON.Input.Raw() to get the
145
- // raw JSON - block.Input is json.RawMessage, not the parsed value.
146
- var in struct {
147
- A int `json:"a"`
148
- B int `json:"b"`
149
- }
150
- if err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &in); err != nil {
151
- log.Fatal(err)
152
- }
153
- result := fmt.Sprintf("%d", in.A+in.B)
154
- // 5. NewToolResultBlock(toolUseID, content, isError) builds the
155
- // ContentBlockParamUnion for you. block.ID is the tool_use_id.
156
- toolResults = append(toolResults,
157
- anthropic.NewToolResultBlock(block.ID, result, false))
158
- }
159
- }
160
-
161
- // 6. Exit when Claude stops asking for tools
162
- if resp.StopReason != anthropic.StopReasonToolUse {
163
- break
164
- }
165
-
166
- // 7. Tool results go in a user message (variadic: all results in one turn)
167
- messages = append(messages, anthropic.NewUserMessage(toolResults...))
168
- }
169
- }
170
- ```
171
-
172
- **Key API surface:**
173
-
174
- | Symbol | Purpose |
175
- |---|---|
176
- | `resp.ToParam()` | Convert `Message` response -> `MessageParam` for history |
177
- | `block.AsAny().(type)` | Type-switch on `ContentBlockUnion` variants |
178
- | `variant.JSON.Input.Raw()` | Raw JSON string of tool input (for `json.Unmarshal`) |
179
- | `anthropic.NewToolResultBlock(id, content, isError)` | Build `tool_result` block |
180
- | `anthropic.NewUserMessage(blocks...)` | Wrap tool results as a user turn |
181
- | `anthropic.StopReasonToolUse` | `StopReason` constant to check loop termination |
182
- | `anthropic.ToolUnionParam{OfTool: &t}` | Wrap `ToolParam` in the union for `Tools:` |
183
-
184
- ---
185
-
186
- ## Anthropic-Defined Tools
187
-
188
- Version-suffixed struct names with `Param` suffix. `Name`/`Type` are `constant.*` types - zero value marshals correctly, so `{}` works. Wrap in `ToolUnionParam` with the matching `Of*` field. Web search and code execution are server-executed; bash and text editor are client-executed (you handle the `tool_use` locally - see `shared/tool-use-concepts.md`).
189
-
190
- ```go
191
- Tools: []anthropic.ToolUnionParam{
192
- {OfWebSearchTool20260209: &anthropic.WebSearchTool20260209Param{}},
193
- {OfBashTool20250124: &anthropic.ToolBash20250124Param{}},
194
- {OfTextEditor20250728: &anthropic.ToolTextEditor20250728Param{}},
195
- {OfCodeExecutionTool20260120: &anthropic.CodeExecutionTool20260120Param{}},
196
- },
197
- ```
198
-
199
- Also available: `WebFetchTool20260209Param`, `ToolSearchToolBm25_20251119Param`, `ToolSearchToolRegex20251119Param`. For the advisor and memory tools, use `BetaAdvisorTool20260301Param` / `BetaMemoryTool20250818Param` in the beta namespace on `client.Beta.Messages.New`.
200
-
201
- ### Advisor tool (beta)
202
-
203
- Server-side - no tool_result round-trip. The advisor model must be >= the executor (top-level) model; invalid pairs return 400.
204
-
205
- ```go
206
- response, err := client.Beta.Messages.New(ctx, anthropic.BetaMessageNewParams{
207
- Model: anthropic.ModelClaudeSonnet4_6,
208
- MaxTokens: 4096,
209
- Tools: []anthropic.BetaToolUnionParam{
210
- {OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
211
- Model: anthropic.ModelClaudeOpus4_8,
212
- }},
213
- },
214
- Messages: []anthropic.BetaMessageParam{ /* ... */ },
215
- Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaAdvisorTool2026_03_01},
216
- })
217
- ```
218
-
219
- ---
220
-