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.ts

Agent 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.ts
import {
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.ts
export { 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.ts
import { 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 action
Agent: [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-agent

Dockerfile

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 files
COPY package*.json ./
COPY pnpm-lock.yaml ./
# Install dependencies
RUN npm install -g pnpm && pnpm install --frozen-lockfile
# Copy source
COPY . .
# Build
RUN pnpm build
# Start agent
CMD ["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.