AutoGen integration

View as Markdown

dial-autogen packages Dial’s operations as Microsoft AutoGen tools, so an AssistantAgent can send messages, receive OTP codes, and place calls as part of its work. It’s the AutoGen sibling of the LangChain integration: each tool is an autogen_core.tools.FunctionTool wrapping the Python SDK client — it adds nothing to the REST contract, it just shapes Dial’s operations into AutoGen tools.

Targeting Microsoft’s newer Agent Framework (the 1.0 successor to AutoGen + Semantic Kernel) instead? Use dial-agentframework. Both expose the same Dial tools; pick the one that matches your stack.

Install

$pip install dial-autogen

This pulls in dial-sdk and autogen-agentchat.

Give the tools to an agent

Build one DialClient, pass it to dial_tools, and hand the list to an agent. Every tool shares that one client — a single connection pool for the whole agent session — and you own its lifecycle (await client.close() when done). Enterprise / Azure AI builds typically drive AutoGen with an Azure OpenAI model client:

1from autogen_agentchat.agents import AssistantAgent
2from autogen_ext.models.openai import AzureOpenAIChatCompletionClient
3from dial_sdk import DialClient, DialConfig
4from dial_autogen import dial_tools
5
6dial = DialClient(DialConfig(api_key="sk_live_...")) # close with `await dial.close()`
7
8model_client = AzureOpenAIChatCompletionClient(
9 azure_deployment="gpt-4o",
10 model="gpt-4o",
11 api_version="2024-10-21",
12 azure_endpoint="https://<your-resource>.openai.azure.com/",
13)
14
15agent = AssistantAgent(
16 name="phone_agent",
17 model_client=model_client,
18 tools=dial_tools(dial),
19 system_message="You operate the team's Dial phone number for SMS, OTP, and voice calls.",
20)

dial_tools returns the full set, all sharing your client — the analog of LangChain’s DialToolkit.get_tools(). AutoGen runs tools in an async loop, so the Dial tools are async-native — there’s no async→sync bridge (the one difference from the CrewAI sibling).

Available tools

Each builder takes your shared DialClient and returns one FunctionTool:

BuilderTool nameAction
list_numbers_toollist_numbersList your phone numbers
purchase_number_toolpurchase_numberProvision a new number (billable)
set_number_properties_toolset_number_propertiesUpdate a number’s nickname or inbound instruction
send_message_toolsend_messageSend an SMS
list_messages_toollist_messagesList recent messages
make_call_toolmake_callPlace an AI voice call
list_calls_toollist_callsList recent calls
get_call_toolget_callFetch one call by id
get_billing_toolget_billingCredit balance, subscription, per-number mode
wait_for_message_toolwait_for_messageBlock until the next inbound SMS arrives, or time out

Or pick individual tools

1from dial_autogen import send_message_tool, wait_for_message_tool
2
3tools = [
4 send_message_tool(dial),
5 wait_for_message_tool(dial),
6]

Handling OTP

The reason an agent needs phone identity: receive a verification code and act on it. wait_for_message blocks until the next inbound SMS arrives, so an agent can trigger a signup that texts a code to your Dial number, read the code, and enter it back into the form.

1agent = AssistantAgent(
2 name="signup_agent",
3 model_client=model_client,
4 tools=dial_tools(dial),
5 system_message="You complete phone-verified signups by reading the OTP sent to our Dial number.",
6)
7
8result = await agent.run(
9 task="Wait up to 120 seconds for the inbound verification code on our Dial number, then report it."
10)
11print(result.messages[-1].content)

A full runnable example is in examples/signup_autogen.ipynb.

send_message is a write action and isn’t idempotent — a re-invoke after a failure can send a duplicate. make_call accepts an idempotency_key. See Retries and idempotency.

Receiving events beyond a single wait

wait_for_message is a one-shot wait, backed by a presence-based stream (not at-least-once — missed events replay only on reconnect within ~2 minutes). To react to inbound SMS or completed calls durably, use the Python SDK’s new_events_connection() directly, or register a webhook (signed and retried at-least-once), and feed events into your agent however suits your app.