The Exoskeleton for your AI Agents.
AI Agents are unpredictable. They hallucinate arguments, ignore safety rails, and make it difficult to understand what went wrong.
Exo provides a strictly typed, deterministic security layer for your AI tools. Every input is validated, every high-risk action requires permission, and every execution is observableβregardless of which SDK you use.
- π‘οΈ Deterministic Safety β Role-based access control with
HIGH/MEDIUM/LOWrisk levels and human-in-the-loop confirmation flows. - π Universal Adapters β Works seamlessly with OpenAI SDK, Vercel AI SDK, and LangChain.
- ποΈ Observability β Zero-dependency lifecycle hooks for logging latency, errors, and custom telemetry.
- π Type-Safe β Built on Zod with full TypeScript inference for both inputs and outputs.
- β‘ Lightweight β No external runtime dependencies beyond Zod.
npm install @fozooni/exo zodimport { z } from "zod";
import { createExoTool, RiskLevel } from "@fozooni/exo";
const weatherTool = createExoTool({
name: "get_weather",
description: "Gets the current weather for a city.",
schema: z.object({
city: z.string().describe("The city name"),
}),
executor: async ({ city }) => {
return { city, temperature: 22, conditions: "sunny" };
},
config: {
riskLevel: RiskLevel.LOW,
},
});
// Execute directly
const result = await weatherTool.execute({ city: "Istanbul" });
console.log(result.data); // { city: 'Istanbul', temperature: 22, conditions: 'sunny' }
// Or get OpenAI-compatible spec
const spec = weatherTool.getOpenAISpec();
// Use with: openai.chat.completions.create({ tools: [spec] })const deleteDatabase = createExoTool({
name: "delete_database",
description: "Permanently deletes a database. DANGEROUS.",
schema: z.object({ confirm: z.literal(true) }),
executor: async () => ({ deleted: true }),
config: {
riskLevel: RiskLevel.HIGH, // Requires admin role
},
});
// β Throws RiskViolationError
await deleteDatabase.execute(
{ confirm: true },
{ user: { id: "1", role: "guest" } },
);
// β
Works
await deleteDatabase.execute(
{ confirm: true },
{ user: { id: "1", role: "admin" } },
);import { Exo, toVercelTool } from "@fozooni/exo";
import { streamText } from "ai";
const exo = new Exo([weatherTool, searchTool]);
// Get all tools as Vercel-compatible object
const tools = exo.getVercelTools();
const result = await streamText({
model: openai("gpt-4o"),
tools,
messages,
});import { createExoTool, createConsoleLogger } from "@fozooni/exo";
const tool = createExoTool({
name: "my_tool",
schema: z.object({}),
executor: async () => ({ ok: true }),
config: {
hooks: createConsoleLogger(),
},
});
await tool.execute({});
// [EXO] βΆ START my_tool {}
// [EXO] β SUCCESS my_tool (0.42ms)// Generate schema with additionalProperties: false
const strictSpec = weatherTool.getOpenAISpec({ strict: true });Intercept and modify execution flow. Useful for logging, caching, or altering arguments.
const loggingMiddleware: ExoMiddleware = async ({ toolName, args, next }) => {
console.log(`Extensions: Running ${toolName}`);
const result = await next();
console.log(`Extensions: Finished ${toolName}`);
return result;
};
const tool = createExoTool({
// ... other options
config: {
middleware: [loggingMiddleware],
},
});Protect your tools from overuse with zero extra infrastructure.
import { createExoTool, createRateLimiter } from "@fozooni/exo";
// Limit to 10 requests per minute
const limiter = createRateLimiter({
windowMs: 60 * 1000,
limit: 10,
// Optional: Custom key generator (defaults to toolName:userId)
keyGenerator: (context) => context.userId,
});
const searchTool = createExoTool({
name: "search",
// ...
config: {
middleware: [limiter],
},
});| Export | Description |
|---|---|
ExoTool |
Main tool class with validation, execution, and spec generation |
Exo |
Registry for managing multiple tools |
createExoTool() |
Factory function with better type inference |
| Export | Description |
|---|---|
toVercelTool() |
Convert to Vercel AI SDK format |
toLangChainTool() |
Convert to LangChain DynamicStructuredTool format |
| Export | Description |
|---|---|
ValidationError |
Thrown when arguments fail Zod validation |
RiskViolationError |
Thrown when a HIGH risk tool is called without permission |
ConfirmationRequiredError |
Thrown when confirmation is needed |
- Middleware pipeline for pre/post processing
- Built-in rate limiting
- Telemetry integrations (OpenTelemetry, Datadog)
- Tool versioning and deprecation support
Contributions are welcome! Please read our contributing guidelines and submit a PR.
git clone https://github.com/fozooni/exo.git
cd exo
npm install
npm testMIT Β© Fozooni