AutoGen Tutorial (TypeScript): handling async tools for intermediate developers
By Cyprian AaronsUpdated 2026-04-21
autogenhandling-async-tools-for-intermediate-developerstypescript
This tutorial shows how to wire async tools into an AutoGen TypeScript agent without blocking the conversation loop. You need this when your tool calls hit databases, HTTP APIs, queues, or internal services that return Promises instead of immediate values.
What You'll Need
- •Node.js 18+ and npm
- •A TypeScript project with
ts-nodeortsx - •
autogeninstalled in your project - •An OpenAI API key set as
OPENAI_API_KEY - •Optional: access to a real async API you want to call from a tool
Step-by-Step
- •Start with a minimal TypeScript project and install the packages you need. Keep the runtime simple so you can isolate whether problems come from AutoGen, TypeScript, or your tool code.
npm init -y
npm install autogen dotenv
npm install -D typescript tsx @types/node
- •Create a basic agent that can call tools. The important part here is that your tool function returns a
Promise, and AutoGen will await it when the model selects the tool.
import "dotenv/config";
import { AssistantAgent } from "autogen";
const agent = new AssistantAgent({
name: "support_agent",
modelClient: {
model: "gpt-4o-mini",
apiKey: process.env.OPENAI_API_KEY!,
},
});
console.log(`Agent ready: ${agent.name}`);
- •Define an async tool using a real function signature and register it with the agent. This example simulates an external lookup with
setTimeout, but the same pattern works for fetch calls, database drivers, or SDKs.
import "dotenv/config";
import { AssistantAgent, type Tool } from "autogen";
const getPolicyStatus: Tool = {
name: "get_policy_status",
description: "Fetch policy status by policy number",
parameters: {
type: "object",
properties: {
policyNumber: { type: "string" },
},
required: ["policyNumber"],
additionalProperties: false,
},
execute: async ({ policyNumber }: { policyNumber: string }) => {
await new Promise((resolve) => setTimeout(resolve, 500));
return {
policyNumber,
status: "active",
updatedAt: new Date().toISOString(),
};
},
};
const agent = new AssistantAgent({
name: "support_agent",
modelClient: {
model: "gpt-4o-mini",
apiKey: process.env.OPENAI_API_KEY!,
},
tools: [getPolicyStatus],
});
- •Run a conversation and let the model decide when to invoke the async tool. Use a prompt that clearly requires external data so you can verify the tool path instead of just free-form text generation.
import "dotenv/config";
import { AssistantAgent, UserMessage, type Tool } from "autogen";
const getPolicyStatus: Tool = {
name: "get_policy_status",
description: "Fetch policy status by policy number",
parameters: {
type: "object",
properties: {
policyNumber: { type: "string" },
},
required: ["policyNumber"],
additionalProperties: false,
},
execute: async ({ policyNumber }: { policyNumber: string }) => {
await new Promise((resolve) => setTimeout(resolve, 500));
return { policyNumber, status: "active" };
},
};
async function main() {
const agent = new AssistantAgent({
name: "support_agent",
modelClient: {
model: "gpt-4o-mini",
apiKey: process.env.OPENAI_API_KEY!,
},
tools: [getPolicyStatus],
});
const result = await agent.run([
new UserMessage("Check policy POL-1007 and tell me if it is active."),
]);
console.log(result.messages.at(-1)?.content);
}
main();
- •Add proper error handling around your async tool. In production you want clear failures for timeouts, bad upstream responses, and malformed inputs rather than silent retries or vague model output.
import { z } from "zod";
const PolicyInputSchema = z.object({
policyNumber: z.string().min(1),
});
const getPolicyStatus = {
name: "get_policy_status",
description: "Fetch policy status by policy number",
parameters: {
type": "object",
properties": {
policyNumber": { type": "string" }
},
required": ["policyNumber"],
additionalProperties": false
},
execute": async (input) => {
const parsed = PolicyInputSchema.parse(input);
try {
await new Promise((resolve) => setTimeout(resolve, 500));
return { ...parsed, status": "active" };
} catch (err) {
throw new Error(`policy lookup failed for ${parsed.policyNumber}`);
}
}
};
- •If your tool calls an external HTTP service, use
fetchand keep the function fully async. This is the pattern you will use most often in real systems because agent tools usually wrap internal APIs.
const fetchCustomerProfile = {
name": "fetch_customer_profile",
description": "Get customer profile from internal service",
parameters": {
type": "object",
properties": {
customerId": { type": "string" }
},
required": ["customerId"],
additionalProperties": false
},
execute": async ({ customerId }: { customerId): Promise<{ customerId:string; tier:string }> => {
const response = await fetch(`https://api.example.com/customers/${customerId}`);
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit