Calling Agents from Routes
Import and invoke agents from your routes
Routes import agents directly and call them using agent.run(). Use agent.validator() for type-safe request validation.
Basic Agent Call
Import an agent and call it in your route:
import { createRouter } from '@agentuity/runtime';
import chat from '@agent/chat';
const router = createRouter();
router.post('/chat', async (c) => {
const { message } = await c.req.json();
const result = await chat.run({ message });
return c.json(result);
});
export default router;The agent receives validated input (if it has a schema) and returns typed output.
With Validation
Use agent.validator() for type-safe request validation:
import { createRouter } from '@agentuity/runtime';
import chat from '@agent/chat';
const router = createRouter();
router.post('/chat', chat.validator(), async (c) => {
const data = c.req.valid('json'); // Fully typed from agent schema
const result = await chat.run(data);
return c.json(result);
});
export default router;Multiple Agents
Import and use multiple agents in the same route file:
import { createRouter } from '@agentuity/runtime';
import chat from '@agent/chat';
import summarizer from '@agent/summarizer';
import teamMembers from '@agent/team/members';
const router = createRouter();
router.post('/process', async (c) => {
const input = await c.req.json();
// Call different agents
const chatResult = await chat.run({ message: input.text });
const summary = await summarizer.run({ content: input.text });
const members = await teamMembers.run({ teamId: input.teamId });
return c.json({ chatResult, summary, members });
});
export default router;Parallel Agent Calls
Run multiple agents concurrently when they don't depend on each other:
import { createRouter } from '@agentuity/runtime';
import sentimentAnalyzer from '@agent/sentiment-analyzer';
import topicExtractor from '@agent/topic-extractor';
import summarizer from '@agent/summarizer';
const router = createRouter();
router.post('/analyze', async (c) => {
const { content } = await c.req.json();
// Run agents in parallel
const [sentiment, topics, summary] = await Promise.all([
sentimentAnalyzer.run({ text: content }),
topicExtractor.run({ text: content }),
summarizer.run({ content }),
]);
return c.json({ sentiment, topics, summary });
});
export default router;Background Agent Calls
Use c.waitUntil() to run agents after responding to the client:
import { createRouter } from '@agentuity/runtime';
import webhookProcessor from '@agent/webhook-processor';
const router = createRouter();
router.post('/webhook', async (c) => {
const payload = await c.req.json();
// Acknowledge immediately
c.waitUntil(async () => {
// Process in background
await webhookProcessor.run(payload);
c.var.logger.info('Webhook processed');
});
return c.json({ received: true });
});
export default router;Webhook Best Practice
Webhook providers expect fast responses (usually under 3 seconds). Use c.waitUntil() to acknowledge receipt immediately and process the payload in the background.
Error Handling
Wrap agent calls in try-catch for graceful error handling:
import { createRouter } from '@agentuity/runtime';
import chat from '@agent/chat';
const router = createRouter();
router.post('/safe-chat', async (c) => {
const { message } = await c.req.json();
try {
const result = await chat.run({ message });
return c.json({ success: true, result });
} catch (error) {
c.var.logger.error('Agent call failed', {
agent: 'chat',
error: error instanceof Error ? error.message : String(error),
});
return c.json(
{ success: false, error: 'Chat processing failed' },
500
);
}
});
export default router;Full Example: Multi-Endpoint API
Combine authentication, validation, and multiple agent calls:
import { createRouter } from '@agentuity/runtime';
import { createMiddleware } from 'hono/factory';
import { s } from '@agentuity/schema';
import chat from '@agent/chat';
import summarizer from '@agent/summarizer';
import sentimentAnalyzer from '@agent/sentiment-analyzer';
import entityExtractor from '@agent/entity-extractor';
const router = createRouter();
// Auth middleware
const authMiddleware = createMiddleware(async (c, next) => {
const apiKey = c.req.header('X-API-Key');
if (!apiKey) {
return c.json({ error: 'API key required' }, 401);
}
const keyData = await c.var.kv.get('api-keys', apiKey);
if (!keyData.exists) {
return c.json({ error: 'Invalid API key' }, 401);
}
c.set('userId', keyData.data.userId);
await next();
});
// Apply auth to all routes
router.use('/*', authMiddleware);
// Chat endpoint - uses chat agent's schema
router.post('/chat', chat.validator(), async (c) => {
const userId = c.var.userId;
const data = c.req.valid('json');
const result = await chat.run({
...data,
userId,
});
// Track usage in background
c.waitUntil(async () => {
await c.var.kv.set('usage', `${userId}:${Date.now()}`, {
endpoint: 'chat',
tokens: result.tokensUsed,
});
});
return c.json(result);
});
// Summarization endpoint - uses summarizer's schema
router.post('/summarize', summarizer.validator(), async (c) => {
const data = c.req.valid('json');
const result = await summarizer.run(data);
return c.json(result);
});
// Multi-agent analysis - uses custom schema
router.post('/analyze',
sentimentAnalyzer.validator({
input: s.object({ content: s.string() }),
}),
async (c) => {
const { content } = c.req.valid('json');
// Run multiple agents in parallel
const [sentiment, entities, summary] = await Promise.all([
sentimentAnalyzer.run({ text: content }),
entityExtractor.run({ text: content }),
summarizer.run({ content, maxLength: 100 }),
]);
return c.json({
sentiment: sentiment.score,
entities: entities.items,
summary: summary.text,
});
}
);
export default router;Validator Pattern
Import the agent you're calling and use agent.validator() for its schema, or pass a custom schema with agent.validator({ input: customSchema }) when the route input differs from the agent's schema.
Type Safety
If your agents have schemas, TypeScript provides full type checking:
import { createAgent } from '@agentuity/runtime';
import { s } from '@agentuity/schema';
// Agent with schema (src/agent/chat/agent.ts)
const chatAgent = createAgent('Chat', {
schema: {
input: s.object({ message: s.string() }),
output: s.object({ response: s.string(), tokensUsed: s.number() }),
},
handler: async (ctx, input) => { ... },
});
// In route - TypeScript knows the types
import chat from '@agent/chat';
router.post('/chat', async (c) => {
const result = await chat.run({ message: 'Hello' });
// result is typed as { response: string, tokensUsed: number }
return c.json({ text: result.response });
});Next Steps
- Creating Agents: Build agents with schemas and handlers
- Calling Other Agents: Agent-to-agent communication patterns
- HTTP Routes: Complete routing guide
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!