Reference Implementations

Business

expense-report-generator

beginner

Aggregate expenses by category, generate formatted reports, cache templates.

APIs Used

ctx.dbctx.filesctx.memoryctx.llm

Capabilities Required

finance/expense/report

What this demonstrates

  • 1ctx.db.query() to aggregate expense records from a database
  • 2ctx.memory for caching report templates across invocations
  • 3ctx.files.write() to persist report output
  • 4ctx.llm for narrative summary generation
typescript
/**
* Expense Report Generator - Production Reference Agent
*
* Canon alignment: KB 105 (Agent SDK)
* Demonstrates: ctx.db, ctx.files, ctx.memory, ctx.llm
*
* Real use case: Aggregate expenses by category, generate PDF-style reports,
* cache report templates in memory.
*/
import { handler, withProvenanceContext } from '@human/agent-sdk';
import type { ExecutionContext } from '@human/agent-sdk';
export const AGENT_ID = 'expense-report-generator';
export const VERSION = '1.0.0';
export const CAPABILITIES = ['finance/expense/report'];
export interface ExpenseReportInput {
/** Date range start (ISO) */
start_date: string;
/** Date range end (ISO) */
end_date: string;
/** Output format */
format?: 'markdown' | 'text';
}
export interface ExpenseReportOutput {
success: boolean;
report_path: string;
total_amount: number;
categories: Array<{ name: string; amount: number; count: number }>;
provenance_id: string;
}
const execute = async (
ctx: ExecutionContext,
input: ExpenseReportInput
): Promise<ExpenseReportOutput> => {
ctx.log.info('Generating expense report', {
start: input.start_date,
end: input.end_date,
});
// Fetch aggregated data from DB (ctx.db())
const db = await ctx.db();
const rows = (await db.query(
`SELECT category, SUM(amount) as total, COUNT(*) as count
FROM expenses
WHERE date >= $1 AND date <= $2
GROUP BY category`,
[input.start_date, input.end_date]
)) as Array<{ category: string; total: number; count: number }>;
const categories = rows.map((r) => ({
name: r.category,
amount: Number(r.total),
count: Number(r.count),
}));
const totalAmount = categories.reduce((sum, c) => sum + c.amount, 0);
// Cache report config in memory (ctx.memory.persistent)
const lastReportKey = `expense_report:last_config`;
await ctx.memory.persistent.set(lastReportKey, JSON.stringify({
start_date: input.start_date,
end_date: input.end_date,
generated_at: new Date().toISOString(),
}));
// Generate report content (ctx.llm with Message[] - best practice for structured prompts)
const summary = await ctx.llm.complete({
prompt: [
{
role: 'system',
content: 'You are a financial analyst. Summarize expense data in one concise sentence.',
},
{
role: 'user',
content: `Summarize: $${totalAmount.toFixed(2)} total across ${categories.length} categories (${categories.map((c) => `${c.name}: $${c.amount.toFixed(2)}`).join(', ')}).`,
},
],
temperature: 0.3,
maxTokens: 100,
});
const format = input.format ?? 'markdown';
let reportContent: string;
if (format === 'markdown') {
reportContent = `# Expense Report\n\n${summary.content}\n\n`;
reportContent += `**Total:** $${totalAmount.toFixed(2)}\n\n`;
reportContent += '| Category | Amount | Count |\n|----------|--------|------|\n';
for (const c of categories) {
reportContent += `| ${c.name} | $${c.amount.toFixed(2)} | ${c.count} |\n`;
}
} else {
reportContent = `Expense Report\n\n${summary.content}\n\nTotal: $${totalAmount.toFixed(2)}\n\n`;
for (const c of categories) {
reportContent += `${c.name}: $${c.amount.toFixed(2)} (${c.count} items)\n`;
}
}
// Write report to files (ctx.files)
const reportPath = `reports/expense-${input.start_date}-${input.end_date}.${format === 'markdown' ? 'md' : 'txt'}`;
await ctx.files.writeText(reportPath, reportContent);
const provenanceId = await ctx.provenance.log(
withProvenanceContext(ctx, {
type: 'expense_report:generated',
status: 'success',
metadata: {
input: { start_date: input.start_date, end_date: input.end_date },
output: { report_path: reportPath, total_amount: totalAmount },
},
})
);
return {
success: true,
report_path: reportPath,
total_amount: totalAmount,
categories,
provenance_id: provenanceId,
};
};
export default handler({
name: AGENT_ID,
id: AGENT_ID,
version: VERSION,
capabilities: CAPABILITIES,
manifest: {
operations: [
{
name: 'generate',
description: 'Aggregate expenses by category and generate a report for the date range',
paramsSchema: {
start_date: { type: 'string', required: true, description: 'Date range start (ISO)' },
end_date: { type: 'string', required: true, description: 'Date range end (ISO)' },
format: { type: 'string', description: 'Output format: markdown or text' },
},
resultKind: 'agent.expense-report-generator.result',
},
],
},
execute,
});

Run the tests

From monorepo root

$ pnpm test:agents:reference

$ pnpm test:agents:reference:verbose

The reference suite runs all 23 agents with createMockExecutionContext(), verifying every ctx.* API call and output shape.

See Also

SDK Reference