Skip to content
Part 7

Making It Real

The Communication Agent

There's one more agent worth building: the Communication Agent. While the other three handle the thinking, this one handles the talking—drafting human-readable summaries and notifications.

Step 50: Create the Communication Agent

Create lib/tools/communication-tools.ts:

// lib/tools/communication-tools.ts

export const formatWeekSummaryTool = tool({
  description: 'Generate a formatted summary of a week\'s schedule,
    suitable for posting or sending to the team.',
  inputSchema: z.object({
    weekStart: z.string().describe('Week start date in YYYY-MM-DD format'),
  }),
  execute: async ({ weekStart }) => {
    const [schedule, employees] = await Promise.all([
      getWeekSchedule(weekStart), getAllEmployees(),
    ])

    const byDay: Record<number, Record<string, string>> = {}
    for (let d = 0; d < 7; d++) {
      byDay[d] = {}
      for (const shift of ['opening', 'mid', 'closing']) {
        const entry = schedule.find(
          s => s.day_of_week === d && s.shift_type === shift
        )
        byDay[d][shift] = entry?.employee_name || '(unassigned)'
      }
    }

    return {
      weekStart,
      scheduleByDay: Object.entries(byDay).map(([day, shifts]) => ({
        day: DAYS_OF_WEEK[Number(day)],
        opening: shifts.opening,
        mid: shifts.mid,
        closing: shifts.closing,
      })),
      totalAssigned: schedule.filter(s => s.employee_name).length,
      gaps: 21 - schedule.filter(s => s.employee_name).length,
    }
  },
})

export const getEmployeeScheduleTool = tool({
  description: 'Get a specific employee\'s shifts for the week.',
  inputSchema: z.object({
    employeeName: z.string(),
    weekStart: z.string(),
  }),
  execute: async ({ employeeName, weekStart }) => {
    const schedule = await getWeekSchedule(weekStart)
    const shifts = schedule
      .filter(s => s.employee_name === employeeName)
      .map(s => ({
        day: DAYS_OF_WEEK[s.day_of_week],
        shift: s.shift_type,
      }))

    return { employee: employeeName, weekStart, shifts, totalShifts: shifts.length }
  },
})

Create lib/agents/communication-agent.ts:

// lib/agents/communication-agent.ts

export const communicationAgent = new ToolLoopAgent({
  model: 'anthropic/claude-sonnet-4.5',
  instructions: `You are the Communication Agent for Fabulosa Books.

Your job is to create clear, friendly, human-readable schedule
communications. You draft messages that could be posted in the
breakroom, sent in a group text, or shared in a team chat.

Tone guidelines:
- Warm and collegial — this is a small, close-knit team
- Use first names
- Be concise but complete
- For individual schedules, mention notable details
- For weekly summaries, format as a clean, readable table

Example tone: "Hey team! Here's next week's schedule. Marcus, you've
got Saturday closing (2-9pm) — thanks for taking that one. Let Alvin
know ASAP if anything doesn't work."`,
  tools: {
    formatWeekSummary: formatWeekSummaryTool,
    getEmployeeSchedule: getEmployeeScheduleTool,
  },
})
Step 51: Add the Communication Agent to the coordinator

Update lib/agents/coordinator-agent.ts to include the new subagent:

// Add to the coordinator's tools:
const draftCommunicationSubagent = tool({
  description: 'Ask the Communication Agent to draft a human-readable
    schedule summary, notification, or message for the team.',
  inputSchema: z.object({
    question: z.string().describe('What to draft or format'),
  }),
  execute: async ({ question }) => {
    const result = await communicationAgent.generate({
      messages: [{ role: 'user', content: question }],
    })
    return { answer: result.text }
  },
})

// Updated coordinator instructions mention four specialists:
// 1. Availability Agent
// 2. Fairness Agent
// 3. Coverage Agent
// 4. Communication Agent
Updated architecture with four specialist agents
Step 52: Test the Communication Agent

Try:

  • "Draft the team schedule for this week" — The coordinator calls the Communication Agent, which formats a clean, readable summary.
  • "What's Billy's schedule this week?" — A personal schedule summary.
  • "Write a message telling the team about next week's schedule" — A friendly notification draft.

Error Handling and Guardrails

Step 53: Handle impossible schedules gracefully

What happens when the agents can't find a valid schedule? Maybe half the team is on vacation. Maybe there's an event requiring extra staff. The coordinator should explain what it couldn't solve and why, rather than failing silently.

Add to the coordinator's instructions:

When you cannot create a complete schedule:
- Explain which constraints conflict
- Fill what you can and clearly mark remaining gaps
- Suggest solutions: "Consider asking Johnny Ray or Carly for extra on-call shifts"
- Never silently leave shifts unassigned — always flag gaps explicitly
The coordinator gracefully handling a difficult week — explaining "I was able to fill 18 of 21 shifts. The remaining 3 gaps are..." with specific suggestions

Cost and Performance

Step 54: Understand the cost implications

Each agent call uses an AI model. In a multi-agent system, the coordinator might call 3–4 subagents per request, each of which might make 2–3 tool calls. That's real usage.

Practical guidance:

  • The coordinator needs the most capable model since it orchestrates complex reasoning. anthropic/claude-sonnet-4.5 is a good default.
  • For simpler agents (Coverage Agent, which mostly validates rules), you could use a faster, cheaper model like anthropic/claude-haiku-4.5.
  • The AI Gateway tracks usage across all providers. Check your dashboard to monitor costs.

To use a cheaper model for a specific agent, just change the model string:

// In coverage-agent.ts — this agent's job is simple enough for Haiku
export const coverageAgent = new ToolLoopAgent({
  model: 'anthropic/claude-haiku-4.5',
  // ... rest stays the same
})
Vercel AI Gateway usage dashboard showing model usage breakdown by agent

Deploy the Final Version

Step 55: Push the complete system
git add -A
git commit -m "Complete multi-agent system: Communication Agent, error handling, cost optimization"
git push

Vercel deploys automatically. Your complete multi-agent scheduling system is live.

The complete multi-agent scheduling system

What You've Learned

Concept What You Learned Where
AI Agents Programs with goals and tools that reason toward solutions Part 2
Tools Specific capabilities (database queries, validation) given to agents Parts 5–6
The Tool Loop Think → use tool → observe → think again → respond Part 5
Specialization Breaking complex problems into focused agents Part 6
Orchestration A coordinator agent that delegates to specialists via tool calls Part 6
Subagent Pattern Wrapping agents as tools for other agents to call Part 6
Streaming UI Real-time agent activity in the browser Parts 5–6
Type Safety InferAgentUIMessage for typed tool results in React Part 5
Graceful Degradation Handling impossible constraints transparently Part 7
Cost Management Using appropriate models for different agent complexity levels Part 7

What's Next

Ideas for extending the system:

  • Employee self-service: An agent that handles shift swap requests between employees
  • Calendar integration: Connect to Google Calendar so the agent knows about personal conflicts
  • Event scheduling: A specialist agent for staffing readings, signings, and community events
  • Authentication: Role-based access so only Alvin and Melissa can trigger full reschedules
  • Notifications: Connect the Communication Agent to email or SMS

The patterns you've learned—tools, agents, orchestration, subagents—apply to any domain. Customer support systems, content pipelines, data analysis workflows, DevOps automation. Anywhere you have a complex task that benefits from specialized reasoning coordinated by a central intelligence, multi-agent orchestration is the architecture.

For Fabulosa Books, the paper schedule on the breakroom wall can finally retire. Not just because the schedule is digital now—but because the thinking is automated. Alvin can focus on curating books, hosting events, and running the store he loves. The agents handle the rest.