handler()

The entry point for every HUMΛN agent. Declare your agent's identity, capabilities, and execute function — HUMΛN handles registration, routing, and lifecycle.

Why declare all this?

The manifest (name, version, capabilities, resources.consumes/produces, state.kind, on[], muscles[]) gives the platform identity, event triggers, and marketplace discovery. Deploy once—you get routing, storage resolution, and "what can this agent do?" for free. Skip it and you reimplement discovery, policy resolution, and audit wiring yourself.

Basic Usage

typescript
import { handler } from '@human/agent-sdk';
export default handler({
name: 'invoice-processor',
description: 'Extracts, validates, and routes invoices with human approval',
capabilities: ['finance/invoice/process'],
version: '1.0.0',
execute: async (ctx, input: InvoiceInput) => {
// ctx has everything: ctx.llm, ctx.call, ctx.memory, ctx.provenance...
const content = await ctx.files.readText(input.invoicePath);
const result = await ctx.llm.complete({ prompt: buildPrompt(content) });
return { success: true, data: JSON.parse(result.content) };
},
});

Options

OptionTypeRequiredDescription
namestringYesAgent name within your org namespace. Used for routing and audit trails.
execute(ctx, input) => Promise<Output>YesYour agent's business logic. Receives ExecutionContext and typed input.
capabilitiesstring[]NoCapability strings for routing and authorization. e.g. ["finance/invoice/process"]
descriptionstringNoHuman-readable description shown in dashboards and the marketplace.
versionstringNoSemantic version. Callers can pin to a version: agent://org/acme/my-agent@v2

Type Safety

Pass input and output types to handler<TInput, TOutput> for full TypeScript inference. The SDK will enforce types at compile time and validate inputs at runtime.

typescript
import { handler, ExecutionContext } from '@human/agent-sdk';
interface MyInput {
query: string;
userId: string;
}
interface MyOutput {
answer: string;
confidence: number;
cost: { usd: number };
}
export default handler<MyInput, MyOutput>({
name: 'semantic-search',
capabilities: ['search/semantic'],
version: '2.1.0',
execute: async (ctx: ExecutionContext, input: MyInput): Promise<MyOutput> => {
const embedding = await ctx.llm.embed(input.query);
const results = await ctx.memory.persistent.search(embedding.vector, { limit: 5 });
const response = await ctx.llm.complete({
prompt: `Answer based on context: ${JSON.stringify(results)}
Question: ${input.query}`,
});
return {
answer: response.content,
confidence: response.confidence ?? 0.8,
cost: response.cost,
};
},
});

Capabilities

Capabilities serve two purposes simultaneously: routing (HUMΛN finds agents that can handle a request) and authorization (the caller's delegation must include the required scope).

typescript
handler({
name: 'multi-capability-agent',
// Capabilities serve two purposes:
// 1. Routing — HUMΛN routes requests to agents with matching capabilities
// 2. Authorization — Delegation must include these scopes for the agent to run
capabilities: [
'finance/invoice/process', // Can process invoices
'finance/approve', // Can approve financial actions
'document-processing', // Can parse documents
],
execute: async (ctx, input) => { ... },
});

Naming convention: Use slash-separated hierarchical strings:domain/resource/action. This enables prefix-based scope checking:finance/* covers all finance capabilities.

Versioning

typescript
// Semantic versioning for controlled rollout
handler({
name: 'report-generator',
version: '3.0.0', // Breaking change from 2.x
// Callers can pin: agent://org/acme/report-generator@v2
// or use latest: agent://org/acme/report-generator
execute: async (ctx, input) => { ... },
});

Return Value

handler() returns a HandlerDefinition object. You export it as the default export of your agent module. HUMΛN's runtime picks it up automatically.

Note: The return value of execute must be JSON-serializable. Complex types (class instances, functions, Buffers) should be converted before returning.

Deep Dives: Developer Passport

See Also