DocsAgent with tools

Agent with tools

Use casesAdvanced25 min

You'll end up with an agent: the model decides on its own when to check the weather, calculate or search the web, and your code runs those actions and hands the results back.

You need: a separate fetch_... key with a spend limit and an allowed-models list (create one), Python 3.10+ and pip install openai.

  1. 1
    Save the code

    File agent.py. Tools: get_weather (a stub instead of a weather service) and calculate (a calculator).

    agent.py
    """
    Agent with tools: the model decides which function to call.
    pip install openai
    python agent.py "What is the weather in London and in Madrid? How much warmer is Madrid?"
    """
    import ast
    import json
    import operator
    import os
    import sys
    
    from openai import OpenAI
    
    MODEL = "deepseek-v4.1-flash"  # or "claude-haiku-5-5", "gpt-6-luna"
  2. 2
    Run it
    bash
    export ZUKKO_API_KEY="fetch_your_key"
    python agent.py "What is the weather in London and in Madrid? How much warmer is Madrid?"

    The model asks for the weather in both cities, then for the difference, then answers. Every call is printed.

  3. 3
    Add web search (optional)

    Paste the code into agent.py before if __name__ == "__main__":, and add "call web_search for fresh facts" to SYSTEM.

    python
    import urllib.error
    import urllib.request
    
    
    def web_search(query: str) -> dict:
        request = urllib.request.Request(
            "https://api.zukko.pro/v1/web-search",
            data=json.dumps({"query": query, "max_results": 5}).encode(),
            headers={
                "Authorization": f"Bearer {os.environ['ZUKKO_API_KEY']}",
                "Content-Type": "application/json",
            },
        )
        try:

    Up to 10 results, about $0.0003–0.0005 per search, counts toward the key's limits. Parameters: POST /v1/web-search.

1The agent loop

  1. Send the conversation with the tools parameter.
  2. Got tool_calls? Run each call and return the result as a message with the tool role and the matching tool_call_id. Go back to step 1.
  3. No tool_calls — content holds the final answer.

MAX_STEPS and MAX_COST_USD stop the agent if it goes in circles. To add your own tool: a function in TOOL_FUNCTIONS and a description in TOOLS.

2Models

ModelPrice per 1M tokens, input / output
deepseek-v4.1-flash$0.03 / $0.10
claude-haiku-5-5$0.05 / $0.20
gpt-6-luna$0.04 / $0.21

Tested through /v1/chat/completions. With the Anthropic SDK and /v1/messages, tools are passed the same way as in the Anthropic API.

3If it doesn't work

What you seeWhat to do
The model answers with text and never calls a toolSharpen the description and the instruction; use a model from the table above
400 after answering a callAnswer every call in tool_calls with a tool message carrying its tool_call_id
The agent calls the same thing in circlesReturn a clear error message from the tool
The model invents argumentsValidate them in the function and return an error — the model will fix it
429 key_daily_limit_reachedThe key limit kicked in — check whether the agent got stuck in a loop
Agent with tools · Zukko Docs