Bring Your Agent
Already have a working Python agent? Connect it to a phone number in under 15 minutes.
Install
Write Your Entrypoint
The entrypoint is an async function called once per call. Set your agent on ctx.session.dialog_machine and call await ctx.session.run().
from unpod import AgentRunner, CallContext
from unpod.adapters.langchain import LangChainAdapter
# Your existing LangChain chain
from your_app import chain
async def entrypoint ( ctx : CallContext) -> None :
ctx.session.dialog_machine = LangChainAdapter(chain)
await ctx.session.run()
Start Your Runner
AgentRunner requires UNPOD_API_KEY to be set in your environment. See the Setup Checklist for all required variables.
AgentRunner(
entrypoint = entrypoint,
agent_id = "my-agent" , # must match agent_id in your Speech Pipe config
).start()
That’s it. Incoming calls to your Unpod number are now routed to your agent.
Supported Adapters
Adapter Import Use when OpenAIAdapterunpod.adapters.openaiOpenAI AsyncOpenAI client — gpt-4o, gpt-4o-mini, etc. AnthropicAdapterunpod.adapters.anthropicAnthropic AsyncAnthropic client — Claude models LangChainAdapterunpod.adapters.langchainLangChain chain with .ainvoke() / .astream() HTTPAdapterunpod.adapters.httpRemote agent API (any language) SuperDialogAdapterunpod.adapters.superdialogsuperdialog DialogMachine / LLMAgent — or assign directly, auto-wrapping handled Custom Implement DialogAdapter protocol Any Python object with turn, stream, assist
OpenAI
from openai import AsyncOpenAI
from unpod import AgentRunner, CallContext
from unpod.adapters.openai import OpenAIAdapter
client = AsyncOpenAI()
async def entrypoint ( ctx : CallContext) -> None :
ctx.session.dialog_machine = OpenAIAdapter(
client = client,
model = "gpt-4o-mini" ,
system_prompt = "You are a helpful support agent. Be concise." ,
)
await ctx.session.run()
AgentRunner( entrypoint = entrypoint, agent_id = "my-agent" ).start()
Anthropic (Claude)
import anthropic
from unpod import AgentRunner, CallContext
from unpod.adapters.anthropic import AnthropicAdapter
client = anthropic.AsyncAnthropic()
async def entrypoint ( ctx : CallContext) -> None :
ctx.session.dialog_machine = AnthropicAdapter(
client = client,
model = "claude-haiku-4-5-20251001" ,
system_prompt = "You are a helpful support agent. Be concise." ,
)
await ctx.session.run()
AgentRunner( entrypoint = entrypoint, agent_id = "my-agent" ).start()
LangChain Chain Requirements
LangChainAdapter expects your chain to accept {"messages": [...]} as input by default. This works with ChatPromptTemplate | ChatModel chains.
If your chain uses a different input key, pass input_key:
# Chain expects {"input": "..."}
LangChainAdapter(chain, input_key = "input" )
Using Session Controls
Inside your entrypoint you can react to call events and control the call:
async def entrypoint ( ctx : CallContext) -> None :
@ctx.session.on ( "user_turn" )
async def _ ( text : str ) -> None :
print ( f "User said: { text } " )
@ctx.session.on ( "call_end" )
async def _ ( reason : str ) -> None :
print ( f "Call ended: { reason } " )
ctx.session.dialog_machine = LangChainAdapter(chain)
await ctx.session.run()
Available hooks: call_start, user_turn, agent_turn, user_partial, interruption, call_end, error.
Writing a Custom Adapter
Implement three methods - no base class required:
class MyAdapter :
async def turn ( self , text : str , context : dict | None = None ) -> str :
"""Return complete response. Called for non-streaming use."""
return my_agent.respond(text)
async def stream ( self , text : str , context : dict | None = None ):
"""Yield response tokens. THIS is the hot path used by session.run()."""
async for token in my_agent.stream(text):
yield token
def assist ( self , text : str ) -> None :
"""Inject a system instruction before the next turn."""
my_agent.set_instruction(text)
stream() is called on every user turn by session.run(). Implement it properly - a single-chunk fallback causes choppy audio.
Next Steps
Setup Checklist One-time resource provisioning: agent, number, voice profile
Session Controls say(), transfer(), recording controls during live calls
SuperDialog State machine framework for structured conversation flows
SuperDialog + Voice Plug a DialogMachine directly into your AgentRunner session