andAgent
Add AI to your workflow. Get structured, typed responses from language models.
Quick Start
import { createWorkflowChain, Agent } from "@voltagent/core";
import { z } from "zod";
import { openai } from "@ai-sdk/openai";
// Create an agent
const agent = new Agent({
name: "Assistant",
// Pass an ai-sdk model directly
model: openai("gpt-4o-mini"),
instructions: "Be concise and helpful",
});
// Use it in a workflow
const workflow = createWorkflowChain({
id: "analyze-text",
input: z.object({ text: z.string() }),
}).andAgent(({ data }) => `Analyze this text: ${data.text}`, agent, {
schema: z.object({
sentiment: z.enum(["positive", "negative", "neutral"]),
summary: z.string(),
}),
});
const result = await workflow.run({ text: "I love this!" });
// Result: { sentiment: "positive", summary: "Expression of enthusiasm" }
How It Works
andAgent
= AI prompt + structured output schema:
.andAgent(
prompt, // What to ask the AI
agent, // Which AI to use
{ schema } // What shape the answer should be
)
Important: andAgent
uses generateObject
under the hood, which means:
- ✅ You get structured, typed responses based on your schema
- ❌ The agent cannot use tools during this step
- ❌ Streaming is not supported (response returns when complete)
Need tools or streaming? Use andThen to call the agent directly with streamText
or generateText
.
Function Signature
// Simple prompt (string)
.andAgent("Summarize this", agent, { schema })
// Dynamic prompt from data (string)
.andAgent(({ data }) => `Analyze: ${data.text}`, agent, { schema })
// Advanced: pass ai-sdk v5 ModelMessage[] (multimodal)
.andAgent(
({ data }) => [
{ role: 'user', content: [{ type: 'text', text: `Hello ${data.name}` }] },
],
agent,
{ schema }
)
// Advanced: pass UIMessage[]
.andAgent(
({ data }) => [
{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: data.prompt }] },
],
agent,
{ schema }
)
Common Patterns
Text Analysis
.andAgent(
({ data }) => `Analyze sentiment of: ${data.review}`,
agent,
{
schema: z.object({
sentiment: z.enum(["positive", "negative", "neutral"]),
score: z.number().min(0).max(1),
keywords: z.array(z.string())
})
}
)
Content Generation
.andAgent(
({ data }) => `Write a ${data.tone} email about ${data.topic}`,
agent,
{
schema: z.object({
subject: z.string(),
body: z.string(),
suggestedSendTime: z.string()
})
}
)
Data Extraction
.andAgent(
({ data }) => `Extract key information from: ${data.document}`,
agent,
{
schema: z.object({
people: z.array(z.string()),
dates: z.array(z.string()),
locations: z.array(z.string()),
mainTopic: z.string()
})
}
)
Dynamic Prompts
Build prompts from workflow data:
.andAgent(
({ data }) => {
// Adjust prompt based on data
if (data.userLevel === "beginner") {
return `Explain in simple terms: ${data.question}`;
}
return `Provide technical details about: ${data.question}`;
},
agent,
{ schema: z.object({ answer: z.string() }) }
)
Chaining with Other Steps
Combine AI with logic:
createWorkflowChain({ id: "smart-email" })
// Step 1: Classify with AI
.andAgent(({ data }) => `What type of email is this: ${data.email}`, agent, {
schema: z.object({
type: z.enum(["support", "sales", "spam"]),
priority: z.enum(["low", "medium", "high"]),
}),
})
// Step 2: Route based on classification
.andThen({
id: "route-email",
execute: async ({ data }) => {
if (data.type === "spam") {
return { action: "delete" };
}
return {
action: "forward",
to: data.type === "support" ? "support@" : "sales@",
};
},
});
Using Tools or Streaming
If you need the agent to use tools or stream responses, use andThen
instead:
import { Agent, createTool } from "@voltagent/core";
import { z } from "zod";
import { openai } from "@ai-sdk/openai";
const getWeatherTool = createTool({
name: "get_weather",
description: "Get weather for a location",
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => {
return { temp: 72, condition: "sunny" };
},
});
const agent = new Agent({
name: "Assistant",
model: openai("gpt-4o-mini"),
tools: [getWeatherTool],
});
// Use andThen to call agent directly with tools
createWorkflowChain({ id: "weather-flow" }).andThen({
id: "get-weather",
execute: async ({ data }) => {
// Call streamText/generateText directly for tool support
const result = await agent.generateText(`What's the weather in ${data.city}?`);
return { response: result.text };
},
});
Best Practices
- Keep prompts clear - AI performs better with specific instructions
- Use enums for categories -
z.enum()
ensures valid options - Add descriptions to schema fields - Helps AI understand what you want
- Handle edge cases - Check for missing or low-confidence results
- Need tools? - Use
andThen
with direct agent calls instead ofandAgent