Reference Implementations

Business

invoice-processor

intermediate

Extract line items, validate totals, categorize expenses, escalate on mismatch.

APIs Used

ctx.filesctx.llmctx.dbctx.provenancectx.escalate()ctx.telemetry.emit

Capabilities Required

finance/invoice/process

What this demonstrates

  • 1ctx.files.readText() to load documents from file storage
  • 2ctx.llm.complete() with a structured JSON extraction prompt
  • 3Fourth Law (P10): ctx.escalate() escalation when computed total ≠ expected total
  • 4ctx.db.insert() for persisting structured invoice records
  • 5ctx.provenance.log() on both success and rejection paths — full audit trail
  • 6ctx.telemetry.emit via emitReferenceAuthorSignal on LLM JSON parse recovery (telemetry.author.reference.*)
typescript
/**
* Invoice Processor - Production Reference Agent
*
* Canon alignment: KB 105 (Agent SDK), KB 22 (HumanOS)
* Demonstrates: ctx.files, ctx.llm, ctx.db, ctx.provenance, ctx.escalate()
*
* Real use case: Extract line items from invoices, validate totals, categorize
* expenses. Escalates to human when totals don't match (Fourth Law).
*/
import { handler, withProvenanceContext } from '@human/agent-sdk';
import type { ExecutionContext } from '@human/agent-sdk';
import { emitReferenceAuthorSignal } from '../../lib/reference-author-telemetry.js';
export const AGENT_ID = 'invoice-processor';
export const VERSION = '1.0.0';
export const CAPABILITIES = ['finance/invoice/process'];
export interface InvoiceProcessorInput {
/** File path to invoice (text or path in file storage) */
invoicePath: string;
/** Expected total for validation (optional) */
expectedTotal?: number;
}
export interface LineItem {
description: string;
quantity: number;
unit_price: number;
amount: number;
}
export interface InvoiceProcessorOutput {
success: boolean;
line_items: LineItem[];
total: number;
vendor?: string;
date?: string;
escalation_reason?: string;
provenance_id: string;
}
const execute = async (
ctx: ExecutionContext,
input: InvoiceProcessorInput
): Promise<InvoiceProcessorOutput> => {
ctx.log.info('Processing invoice', { path: input.invoicePath });
// Load invoice from file storage (ctx.files)
const invoiceContent = await ctx.files.readText(input.invoicePath);
// Extract line items using LLM (ctx.llm)
const extractionResult = await ctx.llm.complete({
prompt: [
{
role: 'system',
content: `Extract invoice line items as JSON. Return format: { "lineItems": [{"description":"","quantity":1,"unit_price":0,"amount":0}], "vendor":"", "total":0, "date":"" }. Only return valid JSON.`,
},
{
role: 'user',
content: `Extract line items from this invoice:\n\n${invoiceContent}`,
},
],
temperature: 0.2,
maxTokens: 2000,
});
let lineItems: LineItem[];
let total: number;
let vendor: string | undefined;
let date: string | undefined;
try {
const parsed = JSON.parse(extractionResult.content) as {
lineItems?: LineItem[];
total?: number;
vendor?: string;
date?: string;
};
lineItems = parsed.lineItems ?? [];
total = parsed.total ?? 0;
vendor = parsed.vendor;
date = parsed.date;
} catch {
await emitReferenceAuthorSignal(ctx, 'invoice_llm_json_parse_recovery', {
invoice_path: input.invoicePath,
});
lineItems = [];
total = 0;
}
// Validate totals - escalate to human on mismatch (Fourth Law, P5 Human-in-Loop)
const computedTotal = lineItems.reduce((sum, item) => sum + item.amount, 0);
const tolerance = 0.01;
if (input.expectedTotal != null && Math.abs(computedTotal - input.expectedTotal) > tolerance) {
const decision = await ctx.escalate({
reason: 'Invoice total mismatch - requires human verification',
context: {
invoice_path: input.invoicePath,
expected_total: input.expectedTotal,
computed_total: computedTotal,
line_items: lineItems,
},
requiredCapability: 'finance/approve',
});
if (!decision.approved) {
const provenanceId = await ctx.provenance.log(
withProvenanceContext(ctx, {
type: 'invoice:escalation_rejected',
status: 'success',
metadata: { input: { invoicePath: input.invoicePath, reason: decision.reason } },
})
);
return {
success: false,
line_items: lineItems,
total: computedTotal,
vendor,
date,
escalation_reason: decision.reason,
provenance_id: provenanceId,
};
}
}
// Store in database (ctx.db())
const db = await ctx.db();
const { id } = await db.insert('invoices', {
invoice_path: input.invoicePath,
total: total,
line_items: JSON.stringify(lineItems),
vendor: vendor ?? null,
date: date ?? null,
processed_at: new Date().toISOString(),
});
// Log to provenance (ctx.provenance)
const provenanceId = await ctx.provenance.log(
withProvenanceContext(ctx, {
type: 'invoice:processed',
status: 'success',
metadata: {
input: { invoicePath: input.invoicePath },
output: { invoice_id: id, total, line_item_count: lineItems.length },
},
})
);
return {
success: true,
line_items: lineItems,
total,
vendor,
date,
provenance_id: provenanceId,
};
};
export default handler({
name: AGENT_ID,
id: AGENT_ID,
version: VERSION,
capabilities: CAPABILITIES,
manifest: {
operations: [
{
name: 'process',
description: 'Extract line items from an invoice, validate totals, and escalate on mismatch',
paramsSchema: {
invoicePath: { type: 'string', required: true, description: 'File path to invoice' },
expectedTotal: { type: 'number', description: 'Expected total for validation' },
},
resultKind: 'agent.invoice-processor.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