Core Building Blocks / AI Agent
The Agent Builder
Define typed agents with models, tools, skills, execution policies, and streaming modes.
AgentBuilder (available via getAgentBuilder on ServiceBuilder after importing @purista/ai-harness) lets you define AI-powered agents. It extends the core service builder with AI-specific configuration for models, tools, and agent execution.
Builder workflow
flowchart LR
A[Import @purista/ai-harness] --> B[Create Agent Builder]
B --> C[Define Schemas]
C --> D[Add Model]
D --> E[Pick Execution Type]
E --> F[Configure Tools]
F --> G[Set Policies]
G --> H[Add to Service]
Step 1 — Import from @purista/ai-harness
import { ServiceBuilder } from '@purista/core'
import '@purista/ai-harness' // registers getAgentBuilder on ServiceBuilder
getAgentBuilder becomes available on every ServiceBuilder instance after importing @purista/ai-harness.
Step 2 — Create the agent builder
import { aiV1ServiceBuilder } from './aiV1ServiceBuilder.js'
const supportAgentBuilder = aiV1ServiceBuilder
.getAgentBuilder('SupportAgent', 'AI customer support agent')
getAgentBuilder is available on every ServiceBuilder instance after importing @purista/ai-harness.
Step 3 — Define schemas
import { z } from 'zod'
supportAgentBuilder
.addPayloadSchema(z.object({
query: z.string().min(1),
conversationId: z.string().optional(),
}))
.addParameterSchema(z.object({
priority: z.enum(['low', 'normal', 'high']).default('normal'),
}))
.addOutputSchema(z.object({
answer: z.string(),
confidence: z.number().min(0).max(1),
sources: z.array(z.string()),
}))
Step 4 — Add a model
supportAgentBuilder.addModel('gpt4', {
model: 'openai/gpt-4',
capabilities: ['object', 'text'],
defaults: {
temperature: 0.7,
maxTokens: 2000,
},
})
Capabilities determine which methods are available:
| Capability | Method |
|---|---|
object | context.harness.models.gpt4.object(prompt, schema) |
text | context.harness.models.gpt4.text(prompt) |
embed | context.harness.models.gpt4.embed(texts) |
rerank | context.harness.models.gpt4.rerank(query, documents) |
Step 5 — Pick execution type
Choose exactly one:
Agent function (custom logic)
supportAgentBuilder.setAgentFunction(async function (context, payload, parameter) {
const model = context.harness.models.gpt4
const result = await model.object(
`Answer this customer query: ${payload.query}`,
z.object({ answer: z.string(), confidence: z.number() })
)
return {
answer: result.answer,
confidence: result.confidence,
sources: [],
}
})
Harness agent (model-driven with tools)
supportAgentBuilder.setHarnessAgent({
systemPrompt: 'You are a helpful customer support agent.',
maxToolCalls: 10,
toolChoice: 'auto',
})
Harness workflow (multi-step orchestration)
supportAgentBuilder.setHarnessWorkflow({
steps: [
{ id: 'classify', type: 'model', prompt: 'Classify the query intent' },
{ id: 'search', type: 'tool', tool: 'searchKnowledgeBase' },
{ id: 'respond', type: 'model', prompt: 'Generate response based on search results' },
],
})
Step 6 — Configure tools
supportAgentBuilder
.canInvoke('UserService', '1', 'getUser')
.canInvoke('OrderService', '1', 'getOrderHistory')
.canInvokeAgent('EscalationAgent', '1')
.useSkills(['customer-support', 'billing'])
.useBuiltInTools(['search', 'calculator'])
Tools are exposed to the model as callable functions. The model decides which to use.
Step 7 — Set policies
Session policy
supportAgentBuilder.setSessionPolicy({
mode: 'conversation',
payloadPath: ['conversationId'],
})
Sandbox policy
supportAgentBuilder.setSandboxPolicy({
enabled: true,
adapter: 'isolated-vm',
})
Response mode
supportAgentBuilder.setResponseMode('stream', {
eventName: 'supportResponseChunk',
})
Streaming mode
supportAgentBuilder.setStreamingMode('stream') // or 'aggregate'
Execution policy
supportAgentBuilder.setExecutionPolicy({
leaseTtlMs: 60_000,
heartbeatIntervalMs: 15_000,
maxAttempts: 2,
maxParallelHandlers: 1,
timeoutMs: 300_000,
})
Execution profile
supportAgentBuilder.setExecutionProfile('longRunning', {
maxRuntimeMs: 600_000,
strict: false,
})
Step 8 — Add to the service
import { aiV1ServiceBuilder } from './aiV1ServiceBuilder.js'
import { supportAgentBuilder } from './supportAgentBuilder.js'
aiV1ServiceBuilder.addAgentDefinition(await supportAgentBuilder.getDefinition())
const aiService = await aiV1ServiceBuilder.getInstance(eventBridge, {
queueBridge,
ai: {
models: {
gpt4: { /* model config */ },
},
},
})
await aiService.start()
Full example
import { ServiceBuilder } from '@purista/core'
import '@purista/ai-harness'
export const aiV1ServiceBuilder = new ServiceBuilder({
serviceName: 'AiService',
serviceVersion: '1',
serviceDescription: 'AI-powered customer support',
})
import { z } from 'zod'
import { aiV1ServiceBuilder } from './aiV1ServiceBuilder.js'
export const supportAgentBuilder = aiV1ServiceBuilder
.getAgentBuilder('SupportAgent', 'AI customer support agent')
.addPayloadSchema(z.object({
query: z.string().min(1),
conversationId: z.string().optional(),
}))
.addOutputSchema(z.object({
answer: z.string(),
confidence: z.number().min(0).max(1),
sources: z.array(z.string()),
}))
.addModel('gpt4', {
model: 'openai/gpt-4',
capabilities: ['object', 'text'],
defaults: { temperature: 0.7 },
})
.setHarnessAgent({
systemPrompt: 'You are a helpful customer support agent.',
maxToolCalls: 10,
toolChoice: 'auto',
})
.canInvoke('UserService', '1', 'getUser')
.canInvoke('OrderService', '1', 'getOrderHistory')
.useSkills(['customer-support'])
.setSessionPolicy({
mode: 'conversation',
payloadPath: 'conversationId',
})
.setResponseMode('stream', {
eventName: 'supportResponseChunk',
})
.setExecutionPolicy({
leaseTtlMs: 60_000,
timeoutMs: 300_000,
})
import { aiV1ServiceBuilder } from './aiV1ServiceBuilder.js'
import { supportAgentBuilder } from './supportAgentBuilder.js'
aiV1ServiceBuilder.addAgentDefinition(await supportAgentBuilder.getDefinition())
const aiService = await aiV1ServiceBuilder.getInstance(eventBridge, {
queueBridge,
ai: {
models: {
gpt4: { provider, model: 'gpt-4.1', capabilities: ['object', 'text'] },
},
},
})
await aiService.start()
Important limitations
canEmitis not implemented onAgentBuildercanConsumeStreamis not implemented onAgentBuilder- Execution types (
setAgentFunction,setHarnessAgent,setHarnessWorkflow) are mutually exclusive — pick exactly one - Model capabilities gate which
context.harness.modelsmethods are available at compile and runtime