Docs
Agents

Agents

The seven built-in agents, how they are structured, and how ToolLoopAgent works.

Agent Structure

Every agent exports a single async function:

export async function streamXxxAgent(
  messages: UIMessage[],
  team: any,
  conversationId: string,
  modelId?: string,
): Promise<StreamTextResult<any, any>>

The function creates a ToolLoopAgent (or streamText for the general agent), streams it, and returns the result to the route handler which pipes it to the client.

ToolLoopAgent vs streamText

ToolLoopAgent — used by all agents except general. It autonomously calls tools in a loop, observing each tool result before deciding to call the next tool or respond with text. The loop continues until the agent produces a text response.

streamText — used only by general-agent.ts. No tools, no loop — just a direct text stream.

The onFinish Pattern

Every agent with a ToolLoopAgent saves its response to the database inside onFinish:

const contentAgent = new ToolLoopAgent({
  model: openai("gpt-4o"),
  tools: contentTools,
  instructions: `...`,
  onFinish: async ({ response }) => {
    await saveAgentResponse(response, { conversationId, teamId: team.id });
  },
});

saveAgentResponse handles everything: inserting the message, saving tool results, and persisting assets.

The prepareCall Pattern (Core Memory Injection)

Agents that use memory fetch the team's core memory record and inject it into the system prompt at runtime:

prepareCall: async (settings) => {
  const coreMemoryRecord = await db.query.memories.findFirst({
    where: and(eq(memories.teamId, team.id), eq(memories.key, "core")),
  });
 
  return {
    ...settings,
    instructions: `
      ${settings.instructions}
      
      --- TEAM CORE MEMORY ---
      ${coreMemoryRecord?.content ?? "No core memory set yet."}
      ------------------------
    `,
  };
},

This is how brand voice, business context, and style preferences persist across conversations.

Agent Reference

AgentModelToolsmaxDuration
generalgpt-4o-miniNone30s
content-creationgpt-4oweb_search, web_extract, generate_outline, format_post, generate_image, memory60s
reel-generatorresolveModel(modelId)web_search, web_extract, generate_reel_script, format_reel, generate_image, memory60s
script-writerresolveModel(modelId)web_search, web_extract, generate_script_outline, format_script, memory60s
thumbnail-creatorresolveModel(modelId)generate_thumbnail_concept, generate_image, memory60s
receipt-scannerresolveModel(modelId)extract_receipt_data60s
legal-analyzerresolveModel(modelId)read_document, analyze_legal_document, send_analysis_email120s

legal-analyzer uses maxDuration = 120 because PDF parsing and deep analysis can exceed 60 seconds. This requires Vercel Pro or higher. See Deploying to Vercel for details.

Model Selection

Agents that accept a modelId parameter pass it to resolveModel() in lib/ai/models.ts. If the ID is not recognized, it falls back to gpt-4o. The orchestrator and content-creation agent always use hardcoded models. See AI Models for the full model registry.