From OpenAI Agents
Migrate an existing OpenAI Agents project to AgentBreeder.
Migrate from OpenAI Agents SDK to AgentBreeder
Time to migrate: ~15 minutes Difficulty: Easy What changes: You add an
agent.yamlfile. Your OpenAI Agents SDK code stays exactly the same.
Before You Start
- You have an existing OpenAI Agents SDK agent (using the
openai-agentspackage) - Your agent code is in
agent.pyormain.pywithrequirements.txt - Python 3.11+ is installed
- Docker is installed and running
- You have installed AgentBreeder:
pip install agentbreeder
The Big Picture
The OpenAI Agents SDK gives you a clean API for building agents with Agent, Runner, function_tool, and Handoff. AgentBreeder does not replace any of that. It wraps your agent in a production container and adds everything you need for enterprise deployment: RBAC, cost tracking, health checks, model fallbacks, and org-wide discoverability.
Key insight: Your agent's simplicity is preserved. AgentBreeder adds zero imports to your code.
Before & After
Before: Raw OpenAI Agents SDK
my-agent/
agent.py # Agent + tools definition
requirements.txt
Dockerfile # you wrote this
fly.toml # or render.yaml, or ECS task def...After: OpenAI Agents SDK + AgentBreeder
my-agent/
agent.py # UNCHANGED
requirements.txt # UNCHANGED
agent.yaml # NEW -- the AG configStep-by-Step Migration
Step 1: Verify your agent structure
AgentBreeder accepts either agent.py or main.py. Your file should export an agent variable -- an openai.agents.Agent instance:
# agent.py
from agents import Agent, function_tool
@function_tool
def lookup_order(order_id: str) -> str:
"""Look up an order by ID."""
return f"Order {order_id}: shipped, arriving tomorrow"
agent = Agent(
name="Support Agent",
instructions="You are a helpful customer support agent...",
tools=[lookup_order],
)The variable must be named agent. If yours is named differently, add an alias:
my_bot = Agent(name="My Bot", ...)
agent = my_bot # alias for AgentBreederStep 2: Create agent.yaml
name: support-agent
version: 1.0.0
description: "Customer support agent with order lookup"
team: support
owner: you@company.com
tags: [openai-agents, support, production]
framework: openai_agents
model:
primary: gpt-4o
fallback: gpt-4o-mini
tools:
- name: lookup_order
type: function
description: "Look up an order by ID"
deploy:
cloud: local
secrets:
- OPENAI_API_KEYStep 3: Validate
agentbreeder validate agent.yamlStep 4: Deploy
agentbreeder deploy agent.yaml --target localStep 5: Test
curl -X POST http://localhost:8080/invoke \
-d '{"input": {"message": "Where is order #12345?"}}' \
-H 'Content-Type: application/json'Step 6: Deploy to cloud
deploy:
cloud: aws
runtime: ecs-fargate
region: us-east-1
scaling:
min: 1
max: 10
target_cpu: 70
resources:
cpu: "0.5"
memory: "1Gi"
secrets:
- OPENAI_API_KEYagentbreeder deploy agent.yaml --target awsConcept Mapping: OpenAI Agents SDK to AgentBreeder
| OpenAI Agents Concept | AgentBreeder Equivalent | Notes |
|---|---|---|
Agent(name, instructions, tools) | Export as agent in agent.py | AG wraps it; does not replace it |
Runner.run(agent, input) | POST /invoke on deployed container | AG server wrapper calls Runner |
function_tool | tools: in agent.yaml | Declare for documentation; implementation stays in your code |
Handoff | subagents: in agent.yaml or orchestration.yaml | AG can also orchestrate handoffs at platform level |
Agent.model | model.primary in agent.yaml | AG adds fallback, gateway, temperature |
Agent.instructions | prompts.system in agent.yaml (optional) | Can reference versioned prompts from registry |
guardrail decorator | guardrails: in agent.yaml | AG adds PII detection, content filter, hallucination check |
RunResult | JSON response from /invoke | Same data, wrapped in AG response format |
Streaming (Runner.run_streamed) | Streaming supported via AG server | SSE endpoint at /stream |
trace / OpenAI tracing | AG tracing (OpenTelemetry) | Automatic, framework-agnostic |
Handling Handoffs
The OpenAI Agents SDK has a Handoff mechanism for transferring control between agents. There are two ways to handle this with AgentBreeder:
Option A: Keep Handoffs in Your Code (Simple)
If your handoff agents are all defined in the same agent.py, they work as-is. AgentBreeder deploys the entire file as one unit:
# agent.py
from agents import Agent, Handoff, function_tool
billing_agent = Agent(
name="Billing",
instructions="Handle billing and payment questions.",
tools=[lookup_invoice],
)
tech_agent = Agent(
name="Tech Support",
instructions="Handle technical issues.",
tools=[check_status, restart_service],
)
triage_agent = Agent(
name="Triage",
instructions="Route customer requests to the right specialist.",
handoffs=[
Handoff(target=billing_agent, description="Billing questions"),
Handoff(target=tech_agent, description="Technical support"),
],
)
# Export the entry point agent
agent = triage_agent# agent.yaml
name: support-triage
framework: openai_agents
model:
primary: gpt-4o
deploy:
cloud: local
secrets:
- OPENAI_API_KEYOption B: Separate Agents + AG Orchestration (Advanced)
Deploy each agent independently and use AG orchestration for cross-agent routing:
# orchestration.yaml
name: support-router
version: 1.0.0
team: support
owner: you@company.com
strategy: router
agents:
triage:
ref: agents/triage-agent
routes:
- condition: "billing"
target: billing
- condition: "technical"
target: tech-support
billing:
ref: agents/billing-agent
tech-support:
ref: agents/tech-support-agent
deploy:
target: localBenefits of Option B:
- Independent scaling (tech support might need more capacity than billing)
- Different teams can own different agents
- Per-agent cost tracking
- Mix frameworks (triage could be OpenAI Agents, billing could be LangGraph)
Preserving the Simple OpenAI API
One of the OpenAI Agents SDK's strengths is its simplicity. AgentBreeder preserves that completely:
Your code before AG:
from agents import Agent, Runner, function_tool
@function_tool
def get_weather(city: str) -> str:
"""Get current weather for a city."""
return f"72F and sunny in {city}"
agent = Agent(
name="Weather Bot",
instructions="Help users check the weather.",
tools=[get_weather],
)
# Local testing
result = await Runner.run(agent, "What's the weather in SF?")
print(result.final_output)Your code after AG:
# Exactly the same file. Zero changes.The only addition is agent.yaml next to it. You can still run python agent.py for local testing without any AgentBreeder dependency.
Adding Governance
Model fallback (protects against OpenAI outages)
model:
primary: gpt-4o
fallback: claude-sonnet-4
gateway: litellmWith LiteLLM gateway, AgentBreeder can transparently fall back to a non-OpenAI model. Your OpenAI Agents SDK code does not need to change -- the gateway translates the API.
Guardrails
guardrails:
- pii_detection
- content_filter
- hallucination_checkThese run as middleware around your agent's responses, before they reach the caller.
Access control
access:
visibility: team
allowed_callers:
- team:support
require_approval: falseMCP servers (tool sidecar injection)
Attach MCP tool servers as sidecars to your agent:
mcp_servers:
- ref: mcp/zendesk
transport: stdio
- ref: mcp/order-managementKnowledge bases
knowledge_bases:
- ref: kb/product-docs
- ref: kb/faq-databaseWhat You Gain
| Feature | OpenAI Agents SDK Only | + AgentBreeder |
|---|---|---|
| Agent definition | Agent() | Same (unchanged) |
| Tool definition | @function_tool | Same (unchanged) |
| Running agent | Runner.run() | Same locally; HTTP endpoint in production |
| Deploy | Manual | agentbreeder deploy agent.yaml |
| Multi-cloud | Manual | One-line change |
| Model fallback | Not built-in | Declarative, cross-provider |
| RBAC | Not available | Automatic |
| Cost tracking | Not available | Per-agent, per-model |
| Guardrails | @guardrail decorator | Declarative + your custom guardrails |
| Agent discovery | Not available | Org-wide registry |
| Health checks | Not available | Automatic |
| Autoscaling | Manual | Declarative |
| Audit trail | Not available | Every invocation logged |
| Multi-agent orchestration | Handoffs (in-process) | Handoffs + cross-service orchestration |
What Stays the Same
- Your
Agentdefinitions (name, instructions, tools) - Your
function_toolimplementations - Your
Handoffconfigurations - Your
Runner.run()invocations for local testing - Your guardrail decorators (AG adds platform-level ones on top)
- Your ability to run standalone:
python agent.py
Troubleshooting
"Missing agent.py or main.py"
AgentBreeder accepts either filename. If your entry point is something else:
# agent.py
from my_bot import agent # re-export"No 'agent' variable found"
The AG server wrapper imports agent from your file. Make sure it is exported at module level:
agent = Agent(name="My Agent", ...) # must be at module level, not inside a functionOpenAI API key not found in container
Add it to secrets:
deploy:
secrets:
- OPENAI_API_KEYFor local deploy, set it in your environment before running agentbreeder deploy, or create a .env file in the agent directory.
Streaming responses
The AG server wrapper supports streaming via Server-Sent Events. The /stream endpoint uses Runner.run_streamed() under the hood.
Multiple agents in one file
If you have multiple agents with handoffs in one file, export the "entry point" agent (the one that receives initial input) as agent:
agent = triage_agent # the first agent that receives inputAG imports this agent and uses it as the entry point. Handoff targets are resolved from the same module automatically.
Container health check fails
The default health check hits /health on port 8080. If your agent's dependencies take time to initialize (downloading models, connecting to databases), the check may time out. Ensure heavy initialization is lazy or happens at import time before the server starts.
Full Example
agent.py:
from __future__ import annotations
import math
from agents import Agent, Runner, function_tool
@function_tool
def web_search(query: str) -> str:
"""Search the web for information on a given query."""
return (
f"Search results for '{query}':\n"
f"1. Wikipedia article on {query}\n"
f"2. Recent news about {query}\n"
f"3. Academic papers related to {query}"
)
@function_tool
def calculator(expression: str) -> str:
"""Evaluate a mathematical expression safely."""
allowed_names = {
"abs": abs, "round": round, "min": min, "max": max,
"pow": pow, "sqrt": math.sqrt, "pi": math.pi, "e": math.e,
}
try:
result = eval(expression, {"__builtins__": {}}, allowed_names)
return str(result)
except Exception as e:
return f"Error: {e}"
agent = Agent(
name="Research Assistant",
instructions=(
"You are a helpful research assistant. Use your tools to find "
"accurate information and provide well-structured answers."
),
tools=[web_search, calculator],
)
async def main() -> None:
"""Run the agent interactively for local testing."""
result = await Runner.run(agent, "What is the square root of 144 plus 25?")
print(f"Agent response: {result.final_output}")
if __name__ == "__main__":
import asyncio
asyncio.run(main())requirements.txt:
openai-agents>=0.1.0
openai>=1.60.0agent.yaml:
name: research-assistant
version: 0.1.0
description: "A research assistant agent built with the OpenAI Agents SDK"
team: examples
owner: dev@agentbreeder.com
tags: [example, openai-agents, research, tools]
framework: openai_agents
model:
primary: gpt-4o-mini
tools:
- name: web_search
type: function
description: "Search the web for information"
- name: calculator
type: function
description: "Evaluate mathematical expressions"
deploy:
cloud: local
secrets:
- OPENAI_API_KEYDeploy:
agentbreeder deploy agent.yaml