Claude-code-plugins-plus-skills anth-core-workflow-a
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/anthropic-pack/skills/anth-core-workflow-a" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-anth-core-workflow-a && rm -rf "$T"
manifest:
plugins/saas-packs/anthropic-pack/skills/anth-core-workflow-a/SKILL.mdsource content
Anthropic Core Workflow A — Tool Use (Function Calling)
Overview
Implement Claude's tool use capability where the model can call functions you define. Claude returns
tool_use content blocks with structured JSON inputs; your code executes the function and returns tool_result blocks. This is the foundation for building AI agents.
Prerequisites
- Completed
setupanth-install-auth - Understanding of the Messages API request/response cycle
- Functions or APIs you want Claude to call
Instructions
Step 1: Define Tools
import anthropic client = anthropic.Anthropic() tools = [ { "name": "get_weather", "description": "Get current weather for a city. Use when the user asks about weather conditions.", "input_schema": { "type": "object", "properties": { "city": { "type": "string", "description": "City name, e.g. 'San Francisco, CA'" }, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature units" } }, "required": ["city"] } }, { "name": "search_database", "description": "Search product database by query string. Returns matching products.", "input_schema": { "type": "object", "properties": { "query": {"type": "string"}, "max_results": {"type": "integer", "default": 10} }, "required": ["query"] } } ]
Step 2: Send Request with Tools
message = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, messages=[{"role": "user", "content": "What's the weather in Tokyo?"}] ) # Claude responds with stop_reason="tool_use" # message.content contains both text and tool_use blocks: # [ # {"type": "text", "text": "I'll check the weather for you."}, # {"type": "tool_use", "id": "toolu_01A...", "name": "get_weather", # "input": {"city": "Tokyo", "units": "celsius"}} # ]
Step 3: Execute Tool and Return Result
def execute_tool(name: str, input_data: dict) -> str: """Route tool calls to actual implementations.""" if name == "get_weather": # Call your weather API return '{"temp": 22, "condition": "partly cloudy", "humidity": 65}' elif name == "search_database": return '{"results": [{"name": "Widget A", "price": 29.99}]}' raise ValueError(f"Unknown tool: {name}") # Extract tool_use blocks and execute tool_results = [] for block in message.content: if block.type == "tool_use": result = execute_tool(block.name, block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, # Must match the tool_use block id "content": result }) # Continue conversation with tool results follow_up = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, tools=tools, messages=[ {"role": "user", "content": "What's the weather in Tokyo?"}, {"role": "assistant", "content": message.content}, {"role": "user", "content": tool_results} ] ) print(follow_up.content[0].text) # "The current weather in Tokyo is 22°C and partly cloudy with 65% humidity."
Step 4: Agentic Loop (Multiple Tool Calls)
def run_agent(user_message: str, tools: list, max_turns: int = 10) -> str: """Run an agentic loop that handles multiple sequential tool calls.""" messages = [{"role": "user", "content": user_message}] for _ in range(max_turns): response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=4096, tools=tools, messages=messages ) # If Claude is done (no more tool calls), return final text if response.stop_reason == "end_turn": return next( (b.text for b in response.content if b.type == "text"), "" ) # Process tool calls messages.append({"role": "assistant", "content": response.content}) tool_results = [] for block in response.content: if block.type == "tool_use": result = execute_tool(block.name, block.input) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": result }) messages.append({"role": "user", "content": tool_results}) return "Max turns reached"
Output
- Tool definitions with JSON Schema input validation
- Agent loop handling sequential tool calls
- Proper
/tool_use
message threadingtool_result
Error Handling
| Error | Cause | Solution |
|---|---|---|
: tool schema invalid | Malformed | Validate against JSON Schema spec |
mismatch | Result ID doesn't match tool_use ID | Copy exactly |
| Claude ignores tools | Description too vague | Add clear "Use when..." descriptions |
| Infinite loop | Claude keeps calling tools | Add guard + |
Tool Choice Options
# Let Claude decide (default) tool_choice={"type": "auto"} # Force Claude to use a specific tool tool_choice={"type": "tool", "name": "get_weather"} # Force Claude to use any tool (must call at least one) tool_choice={"type": "any"}
Resources
Next Steps
For streaming with tools, see
anth-core-workflow-b.