Microsoft Agent Framework integration

View as Markdown

dial-agentframework packages Dial’s operations as Microsoft Agent Framework tools, so an Agent can send messages, receive OTP codes, and place calls as part of its work. The Agent Framework is Microsoft’s production successor to AutoGen and Semantic Kernel — the path for new Azure / enterprise agent builds. It’s a sibling of the LangChain integration: each tool is an agent_framework.FunctionTool wrapping the Python SDK client — it adds nothing to the REST contract, it just shapes Dial’s operations into Agent Framework tools.

Already on the original AutoGen (autogen-agentchat)? Use dial-autogen. Both expose the same Dial tools.

Install

$pip install dial-agentframework

This pulls in dial-sdk and agent-framework-core. The Agent Framework keeps each model provider in its own package, so also install a chat client for your provider — for example agent-framework-openai, or the framework’s Azure integration for Azure OpenAI.

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):

1from agent_framework import Agent
2from agent_framework.openai import OpenAIChatClient # pip install agent-framework-openai
3from dial_sdk import DialClient, DialConfig
4from dial_agentframework import dial_tools
5
6dial = DialClient(DialConfig(api_key="sk_live_...")) # close with `await dial.close()`
7
8agent = Agent(
9 OpenAIChatClient(), # Azure OpenAI builds: swap in the Azure integration's chat client
10 name="phone_agent",
11 instructions="You operate the team's Dial phone number for SMS, OTP, and voice calls.",
12 tools=dial_tools(dial),
13)
14
15result = await agent.run("Text +14155550123 from pn_abc saying our table is ready.")
16print(result.text)

dial_tools returns the full set, all sharing your client — the analog of LangChain’s DialToolkit.get_tools(). The Agent Framework runs tools in an async loop, so the Dial tools are async-native — no async→sync bridge. The Dial tools themselves are identical regardless of which model provider (Azure OpenAI, OpenAI, …) drives the agent.

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_agentframework 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.

1result = await agent.run(
2 "Wait up to 120 seconds for the inbound verification code on our Dial number, then report it."
3)
4print(result.text)

A full runnable example is in examples/signup_agentframework.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.