Skip to main content

Building Agents

Building your own agent — not just wiring up an IDE? Drawbridge returns native tool calls on every key, so the call → tool-call → execute → feed-result → loop cycle works with whichever SDK you already use. This page covers which API mode to pick, the loop itself, and how to migrate an existing OpenAI or Anthropic agent.

Which API mode should I use?

All three formats return native tool calls automatically — Drawbridge routes any request carrying tool definitions to the channel that does. So pick by the SDK you already have, not by capability: capability is identical across all three.

You're using…EndpointBase URL
OpenAI SDK / an OpenAI-ecosystem agent framework/v1/chat/completions.../v1
Codex / an OpenAI Responses-style agent/v1/responses.../v1
Anthropic SDK / a Claude-ecosystem agent/v1/messages... (no /v1)

One key, one rate. You don't choose a tool mode or swap keys. Send tool definitions and you get native tool calls back; send plain chat and you get text. Same key, same model id, same per-token price either way.

Build an agent loop

An agent is just a loop: call the model with your tool definitions, run any tool it asks for, feed the result back, and repeat until it stops asking. The shape is the same in both SDKs — only the message-history format differs.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.drawbridge-tech.com/v1", api_key="sk-...")
tools = [{
    "type": "function",
    "function": {
        "name": "write_file",
        "description": "Write text content to a file.",
        "parameters": {
            "type": "object",
            "properties": {"path": {"type": "string"}, "content": {"type": "string"}},
            "required": ["path", "content"],
        },
    },
}]
messages = [{"role": "user", "content": "Create proof.txt containing OK."}]

while True:
    resp = client.chat.completions.create(model="smart", messages=messages, tools=tools)
    msg = resp.choices[0].message
    if not msg.tool_calls:
        break  # model is done
    messages.append(msg)  # echo the assistant turn (with its tool_calls)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = run_tool(call.function.name, args)  # you execute it
        # feed the result back as a "tool" message keyed by tool_call_id
        messages.append({"role": "tool", "tool_call_id": call.id, "content": result})

The rule that bites everyone: feed each tool result back keyed to the call it answers — a role:"tool" message with the matching tool_call_id (OpenAI), or a tool_result block with the matching tool_use_id (Anthropic). Echo the assistant turn first, then the result, before you call again.

Migrating from OpenAI or Anthropic

Already have an agent on the official OpenAI or Anthropic API? It's a near drop-in: change the base URL and key, switch the model id, and keep the rest of your code — tools, streaming, and message handling are unchanged.

from openai import OpenAI

client = OpenAI(
-   base_url="https://api.openai.com/v1",
-   api_key="sk-openai-...",
+   base_url="https://api.drawbridge-tech.com/v1",
+   api_key="sk-drawbridge-...",
)

# model -> "smart" or a Claude id like "claude-opus-4-8"
# everything else (tools, streaming, messages) stays the same

What doesn't carry over: provider-specific model ids — use smart or a Claude id like claude-opus-4-8, not gpt-4o. And reasoning/thinking content isn't returned, so don't depend on a reasoning trace in your loop.

Caveats that matter for agents

  • No reasoning trace. Thinking/reasoning content is not returned. Tool loops work fine — just don't build logic that reads a chain-of-thought field.
  • Usage tokens are credit-derived. Token counts in the usage block are a billing-consistent figure, not a raw token count. Use them for cost, not for exact context-window math.
  • Tool requests fail clean, never silently. If a tool-bearing request can't be served natively, you get a clean error — not a plain-text answer pretending to be a tool result. Treat a 5xx as a retry, not as agent output.

Related