Calling Agents
Code workflows handle deterministic logic well, but sometimes you need AI intelligence — for summarizing, writing, or making decisions. The invokeWorkflow function lets you embed AI capabilities within code workflows.
When to use invokeWorkflow
Use invokeWorkflow for tasks that need intelligence:
- Writing — Composing emails, summaries, reports
- Summarizing — Condensing information
- Deciding — Making judgments about content
- Analyzing — Understanding context or sentiment
Use regular code for deterministic work:
- Filtering — Removing items by criteria
- Formatting — Structuring output
- Aggregating — Grouping or counting
- Iterating — Processing lists
Defining agents
Agents are defined in the workflow’s configuration:
{
"agents": {
"summary_writer": {
"description": "Writes friendly email summaries",
"prompt": "Given a list of emails, write a 2-3 sentence intro summarizing the day's activity and a brief outro.",
"outputSchema": {
"intro": "string",
"outro": "string"
}
}
}
}Each agent has:
- description — What the agent does (for documentation)
- prompt — Instructions for the AI
- outputSchema — Structure of the expected output
Using invokeWorkflow
const result = await invokeWorkflow({
agent: { type: "name", name: "summary_writer" },
context: {
emails,
count: emails.length
},
sync: true
});
if (!result.success) {
throw new Error(result.error || "Agent failed");
}
// result.result.intro and result.result.outro are now availableThe context object is passed to the agent and available in its prompt. The agent returns a result object with success, result, and optionally error. The result field contains structured output matching the agent’s outputSchema.
Example: Smart summary
import { step, tool, invokeWorkflow, complete } from './workflow-runtime';
// Gather data
const emails = await step('gather', async () => {
return await tool('search_emails', { query: 'newer_than:1d is:unread' });
});
// Deterministic formatting
const formatted = await step('format', async () => {
return emails.map(e => `- ${e.subject} (from ${e.from})`).join('\n');
});
// AI-driven writing
const summary = await step('summarize', async () => {
const result = await invokeWorkflow({
agent: { type: "name", name: "writer" },
context: {
emailCount: emails.length,
emailList: formatted
},
sync: true
});
if (!result.success) throw new Error(result.error || "Writer agent failed");
return result.result;
});
// Send the result
await step('send', async () => {
await tool('send_email_to_user', {
subject: 'Daily Summary',
body: `${summary.intro}\n\n${formatted}\n\n${summary.outro}`
});
});
complete();Agent configuration examples
Summarizer
{
"summary_writer": {
"description": "Writes concise summaries",
"prompt": "Summarize the provided content in 2-3 sentences. Be concise and highlight the most important points.",
"outputSchema": {
"summary": "string"
}
}
}Categorizer
{
"email_categorizer": {
"description": "Categorizes emails by type",
"prompt": "Analyze the email and categorize it. Return one of: important, newsletter, notification, spam, other.",
"outputSchema": {
"category": "string",
"confidence": "number"
}
}
}Writer
{
"reply_writer": {
"description": "Drafts email replies",
"prompt": "Draft a professional reply to this email. Be helpful and concise. Match the tone of the original.",
"outputSchema": {
"subject": "string",
"body": "string"
}
}
}Best practices
Keep agent prompts focused. Each agent should do one thing well. Use multiple agents for different tasks.
Use outputSchema. Structured output is easier to work with in code than free-form text.
Provide rich context. The more relevant information you pass in context, the better the agent’s output.
Separate AI from logic
Keep AI work in invokeWorkflow, logic in code:
// Good: AI does writing, code does structure
const result = await invokeWorkflow({
agent: { type: "name", name: "analyzer" },
context: { email },
sync: true
});
const analysis = result.result;
const formatted = `Priority: ${analysis.priority}\nSummary: ${analysis.summary}`;
// Avoid: Mixing concerns
const result = await invokeWorkflow({
agent: { type: "name", name: "do_everything" },
context: { email },
sync: true
});
// The agent is trying to format AND analyze AND decideRelated
- Code Workflows — Overview
- Steps & Caching — How replay works