summaryrefslogtreecommitdiffhomepage
path: root/cc/02-anthropic-tool-format.md
diff options
context:
space:
mode:
Diffstat (limited to 'cc/02-anthropic-tool-format.md')
-rw-r--r--cc/02-anthropic-tool-format.md90
1 files changed, 90 insertions, 0 deletions
diff --git a/cc/02-anthropic-tool-format.md b/cc/02-anthropic-tool-format.md
new file mode 100644
index 0000000..3b2888c
--- /dev/null
+++ b/cc/02-anthropic-tool-format.md
@@ -0,0 +1,90 @@
+# Anthropic Tool Format — What Claude Actually Expects
+
+## The Correct Anthropic API Tool Format
+
+```json
+{
+ "tools": [
+ {
+ "name": "tool_name",
+ "description": "What this tool does",
+ "input_schema": {
+ "type": "object",
+ "properties": {
+ "param1": {
+ "type": "string",
+ "description": "What param1 is"
+ }
+ },
+ "required": ["param1"]
+ }
+ }
+ ],
+ "tool_choice": { "type": "auto" }
+}
+```
+
+### Key requirements
+
+| Field | Type | Required | Notes |
+|-------|------|----------|-------|
+| `name` | string | **Yes** | Must match `^[a-zA-Z0-9_-]{1,64}$` |
+| `description` | string | Strongly recommended | Claude uses this to decide when to call |
+| `input_schema` | object | **Yes** | JSON Schema; root must have `type: "object"` |
+| `input_schema.type` | string | **Yes** | MUST be `"object"` |
+| `input_schema.properties` | object | Recommended | Each property needs `type` and `description` |
+| `input_schema.required` | string[] | Optional | Lists required property names |
+
+### Anthropic does NOT support in input_schema
+
+1. **`$schema`** — JSON Schema meta-keyword; Anthropic rejects it
+2. **`additionalProperties`** — Not supported; can cause silent schema rejection
+3. **`default`** — Not part of Anthropic's JSON Schema subset
+4. **`type` as array** (e.g. `["string", "null"]`) — Rejected
+5. **`type: "null"`** — Rejected
+6. **`nullable`** keyword — Not supported
+7. **`anyOf` / `oneOf` / `allOf`** — Not supported (combiners)
+8. **`$ref` / `$defs` / `$dynamicRef`** — Not supported
+9. **`propertyNames`** — Not supported
+
+## What Claude Code (the CLI) Uses Internally
+
+Claude Code has its OWN internal tool definitions. They use a specific format that Claude has been trained on extensively. When you use Claude outside of Claude Code, the model loses:
+
+1. **The exact tool descriptions** it was trained on in Claude Code
+2. **The precise schema format** Claude Code uses
+3. **The system prompt** that tells Claude to use tools proactively
+4. **The billing/identity headers** that tell Anthropic this is a "real" CLI session
+
+### The billing header trick
+
+From `packages/core/src/credentials/claude.ts`:
+
+```
+x-anthropic-billing-header: cc_version=2.1.112.xxx; cc_entrypoint=sdk-cli; cch=xxxxx;
+```
+
+And the identity preamble:
+```
+"You are Claude Code, Anthropic's official CLI for Claude."
+```
+
+These are mirrored from opencode, but **they go beyond what the raw API needs**. They're hacks to get Anthropic's backend to treat the request as coming from Claude Code.
+
+## Why Claude Opus "Thinks Forever"
+
+Common causes when tools don't get called:
+
+1. **Tool schema has unsupported fields** → Anthropic silently ignores the tool → Claude never sees it → Claude just talks
+2. **Missing description on parameters** → Claude doesn't know what values to provide → stalls
+3. **`input_schema` missing `type: "object"`** → Anthropic rejects the tool entirely
+4. **`tool_choice` is wrong** → Set to `"none"` or Claude decides not to use tools
+5. **System prompt doesn't instruct tool use** → Claude doesn't realize it should call tools
+6. **Anthropic beta headers missing** → Extended thinking or new features might not work
+7. **Thinking budget too high** → Claude uses all tokens thinking and never gets to tool calls
+
+## Sources
+
+- https://docs.anthropic.com/en/docs/build-with-claude/tool-use
+- https://docs.aimlapi.com/capabilities/anthropic
+- https://sdk.vercel.ai/providers/ai-sdk-providers/anthropic