Chapter 18 · Capstone 2: Slack On-Call Assistant (with Framework Comparison)
Chapter goals: Synthesize channels, durability, and subagents to build a Slack on-call assistant, and clarify the适用 boundary between Flue, Mastra, and pi-agent-core with a comparison table.
18.1 Capstone: Slack On-Call Assistant
Goal: someone @-mentions the bot in the on-call channel to report a故障 → the agent auto-classifies → for severe incidents, delegates to a subagent to draft an incident report → posts the result back to the channel.
// agents/oncall.ts — on-call assistant main agent
'use agent';
import { useModel, useSandbox, useSkill, useTool, useSubagent } from '@flue/runtime';
import { virtual } from '@flue/runtime/sandbox';
import incident from '../skills/incident/SKILL.md';
import { postSlackMessage, queryMetrics } from '../tools/ops.ts';
// Declare a subagent: the "expert" specialized in writing incident reports
useSubagent({
name: 'report-writer',
description: 'Draft a structured incident report (timeline/impact/review items) from故障 context',
prompt: `You are an SRE report expert. Input is the incident tier and key metrics.
Output a Markdown report with three sections: [Timeline] [Impact] [Improvement Items].`,
});
export function OnCall() {
useModel('anthropic/claude-sonnet-4-6');
// This assistant only queries metrics and sends messages; virtual sandbox suffices (least privilege)
useSandbox(virtual());
useSkill(incident);
useTool(queryMetrics);
useTool(postSlackMessage);
return `
Upon receiving an on-call channel message:
1. Classify per SKILL.md: P0 (全站不可用) / P1 (核心功能受损) / P2 (一般问题);
2. P2: give处理建议 directly and reply;
3. P0/P1: call query_metrics to pull the last 30 minutes of metrics as evidence;
4. Delegate to the report-writer subagent to generate the incident report;
5. Use post_slack_message to reply with the conclusion and report link.
`;
}// src/channels/slack.ts — Slack channel接入
import { defineChannel } from '@flue/runtime';
export const slackChannel = defineChannel({
name: 'oncall-slack',
provider: 'slack', // Flue handles Slack signature verification
});// src/main.ts — assembly: channel + durability + observability
import { createApp } from '@flue/runtime/node';
import { postgresAdapter } from '@flue/postgres';
import { observe } from '@flue/runtime';
import { Pool } from 'pg';
import { slackChannel } from './channels/slack.ts';
// Observability: error alerts + daily token cost (Chapter 13)
observe((event) => {
if (event.type === 'error') console.error('[ALERT]', event);
});
createApp({
database: postgresAdapter({ // Durability: on-call records survive crashes
pool: new Pool({ connectionString: process.env.DATABASE_URL }),
}),
})
.channel(slackChannel, { secret: process.env.SLACK_SIGNING_SECRET! })
.listen(3000);This example ties together the main threads from Chapters 1–17: channel inbound → least-privilege sandbox → skill methodology → tool execution → subagent delegation → durable storage → observer monitoring.
18.2 Framework Comparison: Flue vs Mastra vs pi-agent-core
All three frameworks solve "building agents" in the TypeScript ecosystem, but their定位差异明显:
| Dimension | Flue | Mastra | pi-agent-core |
|---|---|---|---|
| Positioning | Programmable Agent Harness | Full-stack AI应用框架 | Minimal Agent runtime |
| Core abstraction | 'use agent' function + harness | Agent / Workflow / Memory classes | Agent class + event stream |
| Unique capabilities | Sandboxes, Channels, Durability contract | Workflow graph engine, Evals, Studio | Unified multi-Provider LLM API, minimal心智负担 |
| Execution environment | Three built-in sandboxes (virtual/local/remote container) | Depends on host environment; no built-in sandbox concept | No built-in sandbox (Pi官方 recommends containerization) |
| Inbound events | Channels (verified HTTP ingress) | Integrated into Next.js/Node app; received自行 | Implement自行 |
| Persistence | Durability contract + Postgres adapter | Storage layer + suspend/resume | SQLite session backend (community包) |
| Deployment shapes | Node / Workers / GitHub Actions / GitLab / Render | Node service / Vercel / standalone server | Embedded as a library in your process |
| Suitable for | Production agent teams needing "autonomous work" | AI products with UI, heavy workflow orchestration | Minimal dependency, full runtime control |
// Same task across three frameworks: weather tool call
// Flue —— declarative assembly, harness handles session/sandbox
'use agent';
import { useModel, useTool } from '@flue/runtime';
import getWeather from '../tools/weather.ts';
export function Weather() {
useModel('anthropic/claude-sonnet-4-6');
useTool(getWeather);
return 'Fetch current weather for the user\'s location.';
}
// Mastra —— class-based, explicit tool definition
import { Agent } from '@mastra/core/agent';
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
const weatherTool = createTool({ /* ... */ });
export const weatherAgent = new Agent({
id: 'weather',
model: 'anthropic/claude-sonnet-4-6',
tools: { weatherTool },
});
// pi-agent-core ——极简, function + event流
import { Agent } from 'pi-agent-core';
const agent = new Agent({ model: 'claude-sonnet-4-6' });
agent.on('tool_call', (tool) => { /* ... */ });18.3 How to Choose
- Need自主干活 with沙箱隔离 + 事件驱动 + Durability合约? → Flue;
- Need带 UI 的 AI产品 with Workflow 图引擎 + Evals + Studio? → Mastra;
- Need极简 + 完全掌控运行时 + 最小依赖? → pi-agent-core.
18.4 Chapter Summary
- Capstone: Slack on-call assistant using channels + virtual sandbox + incident skill + query/post tools + report-writer subagent + Postgres durability;
- Framework comparison: Flue (harness + sandboxes + channels + durability) vs Mastra (full-stack + workflows + evals + Studio) vs pi-agent-core (minimal + embedded);
- Choose based on needs: autonomous production agents → Flue; UI products with heavy orchestration → Mastra; minimal embedded runtime → pi-agent-core.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. What sandbox is used for the on-call assistant and why?
2. What is the role of the report-writer subagent?
3. Why is Postgres used in this capstone?
4. When should you choose Flue over Mastra?
🛠️ Hands-On Exercises
- Build the full Slack on-call assistant: channel → agent → tools → subagent → Postgres durability; test with a simulated Slack webhook.
- Compare the code structure with a Mastra equivalent; note the differences in abstraction (function vs class).
- Deploy to a local Node server; send a simulated P0 incident via curl and verify the subagent report is generated and posted back.
Capstone 2 complete. Next: Capstone 3: Code Review Agent.