Custom Agents
Build your own agents for specialized use cases.
Overview
While reference agents cover common use cases, you can build custom agents for specialized needs. Custom agents use the same SDK and infrastructure but with your own logic and capabilities.
Start with a reference agent when possible and customize from there. Build from scratch only when your use case is significantly different.
Project Setup
Create a new agent project:
bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Create new agent project$ mkdir my-custom-agent && cd my-custom-agent$ pnpm init # Install SDK and dependencies$ pnpm add @hyperfold/actions-sdk$ pnpm add -D typescript @types/node # Initialize TypeScript$ npx tsc --init # Create project structure$ mkdir -p src/{handlers,tools,utils}$ touch src/index.ts src/agent.tsAgent Structure
Basic structure of a custom agent:
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// src/agent.tsimport { HyperfoldAgent, OnACPEvent, OnSchedule, OnEndpoint, getProduct, calculateDynamicPrice, sendEmail,} from '@hyperfold/actions-sdk'; @HyperfoldAgent({ name: 'my-custom-agent', type: 'custom', model: { provider: 'openai', model: 'gpt-4o', temperature: 0.7, }, systemPrompt: ` You are a specialized agent for [your use case]. [Your custom instructions here] `, capabilities: ['custom_capability'], integrations: { catalog: 'default', payments: 'stripe', },})export class MyCustomAgent { // Handle custom ACP event @OnACPEvent('custom_action') async handleCustomAction(data: CustomActionData) { // Your custom logic here return { success: true, result: data }; } // Scheduled task @OnSchedule('0 9 * * *') async dailyTask() { // Run daily at 9 AM await this.processDaily(); } // Custom HTTP endpoint @OnEndpoint('/custom/webhook') async handleWebhook(request: Request) { const payload = request.body; await this.processWebhook(payload); return { received: true }; } // Internal methods private async processDaily() { // Your daily processing logic } private async processWebhook(payload: any) { // Your webhook processing logic }} // src/index.tsexport { MyCustomAgent } from './agent';Local Testing
Test your agent locally before deployment:
bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Create test file$ touch src/test.ts // src/test.tsimport { TestRunner } from '@hyperfold/actions-sdk/testing';import { MyCustomAgent } from './agent'; const runner = new TestRunner(MyCustomAgent); async function test() { // Test custom action const result = await runner.invoke('custom_action', { data: { test: true }, }); console.log('Custom action result:', result); // Test with mock context const quotResult = await runner.invoke('quote', { productId: 'prod_test', offer: 100, context: { customer_id: 'cust_test', loyalty_tier: 'gold', }, }); console.log('Quote result:', quoteResult);} test(); # Run tests$ npx ts-node src/test.ts # Or use the CLI simulator$ hyperfold sim local ./src/agent.ts > [Local] Starting local agent simulation...> [Ready] Agent loaded. Type messages to interact. You: Test my custom actionAgent: [Executing custom_action handler...]Agent: Custom action completed successfully.Deployment
Deploy your custom agent:
bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Build the agent$ pnpm build # Deploy to Hyperfold$ hyperfold agent deploy ./dist > [Scan] Found agent: my-custom-agent> [Build] Packaging agent code...> [Push] Uploading to Container Registry...> [Deploy] Creating Cloud Run service...> [Config] Setting up Firestore collections... ✓ Agent deployed successfully! Name: my-custom-agent URL: https://my-custom-agent-xyz.run.app Status: active # Deploy with environment variables$ hyperfold agent deploy ./dist \ --set-env="API_KEY=xxx" \ --set-env="FEATURE_FLAG=true" # Deploy to specific environment$ hyperfold agent deploy ./dist --env=production # Verify deployment$ hyperfold agent get my-custom-agentDockerfile
The SDK auto-generates a Dockerfile, but you can customize it:
dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Dockerfile (auto-generated, customize if needed)FROM node:20-slim WORKDIR /app # Copy package filesCOPY package*.json ./COPY pnpm-lock.yaml ./ # Install dependenciesRUN npm install -g pnpm && pnpm install --frozen-lockfile # Copy sourceCOPY . . # BuildRUN pnpm build # Start agentCMD ["node", "dist/index.js"]Examples
Example custom agents for common use cases:
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Example 1: Subscription Management Agent@HyperfoldAgent({ name: 'subscription-agent', type: 'custom', capabilities: ['subscribe', 'manage_subscription'],})export class SubscriptionAgent { @OnACPEvent('subscribe') async handleSubscribe(productId: string, plan: string, context: BuyerContext) { const product = await getProduct(productId); // Create subscription const subscription = await this.stripe.subscriptions.create({ customer: context.stripe_customer_id, items: [{ price: product.stripe_price_id }], }); return { status: 'subscribed', subscription_id: subscription.id, next_billing: subscription.current_period_end, }; } @OnSchedule('0 0 * * *') // Daily at midnight async processRenewals() { const expiringToday = await this.getExpiringSubscriptions(); for (const sub of expiringToday) { await this.sendRenewalReminder(sub); } }} // Example 2: Inventory Alert Agent@HyperfoldAgent({ name: 'inventory-alert-agent', type: 'custom',})export class InventoryAlertAgent { @OnSchedule('*/15 * * * *') // Every 15 minutes async checkInventoryLevels() { const lowStock = await this.catalog.findLowStock({ threshold: 10, }); if (lowStock.length > 0) { await this.sendSlackAlert({ channel: '#inventory-alerts', message: `⚠️ Low stock alert: ${lowStock.length} products below threshold`, products: lowStock, }); } } @OnEndpoint('/reorder', { method: 'POST' }) async triggerReorder(request: Request) { const { product_id, quantity } = request.body; await this.createPurchaseOrder(product_id, quantity); return { status: 'reorder_created' }; }} // Example 3: Customer Success Agent@HyperfoldAgent({ name: 'customer-success-agent', type: 'custom',})export class CustomerSuccessAgent { @OnEvent('order.delivered') async followUpAfterDelivery(order: Order) { // Wait 3 days then send feedback request await this.scheduleTask({ delay: '3d', action: 'send_feedback_request', data: { order_id: order.id, customer_id: order.customer_id }, }); } @OnSchedule('0 10 * * 1') // Monday at 10 AM async weeklyCustomerOutreach() { // Find customers who haven't ordered in 30+ days const dormant = await this.findDormantCustomers({ days: 30 }); for (const customer of dormant) { const recommendations = await this.recommender.getPersonalized(customer.id); await this.sendReEngagementEmail(customer, recommendations); } }}Need help? Check the Cookbook for complete agent implementation examples.