@kadi.build/core
v0.0.1-alpha.15
Published
A module that is a comprehensive toolkit for developers integrating with the KADI infrastructure.
Downloads
81
Readme
@kadi.build/core
Framework for building distributed abilities with multiple transport protocols
Installation
npm install @kadi.build/coreQuick Start
Creating an Ability
import { KadiClient, z } from '@kadi.build/core';
const ability = new KadiClient({
name: 'math-ability',
version: '1.0.0'
});
// Register tool with Zod schemas (recommended)
ability.registerTool({
name: 'add',
description: 'Add two numbers',
input: z.object({
a: z.number().describe('First number'),
b: z.number().describe('Second number')
}),
output: z.object({
result: z.number().describe('Sum of a and b')
})
}, async ({ a, b }) => {
return { result: a + b };
});
// Start serving (native, stdio, or broker)
await ability.serve('stdio');Loading and Using Abilities
import { loadAbility } from '@kadi.build/core';
const math = await loadAbility('math-ability', 'stdio');
const result = await math.add({ a: 5, b: 3 });
console.log(result); // { result: 8 }Tool Registration (Three Ways)
1. With Zod Schemas (Recommended)
Zod provides type-safe schemas with 70% less code than JSON Schema:
import { KadiClient, z } from '@kadi.build/core';
const ability = new KadiClient({ name: 'example' });
ability.registerTool({
name: 'processData',
description: 'Process user data',
version: '1.0.0',
input: z.object({
name: z.string().min(1).describe('User name'),
age: z.number().int().positive().optional().describe('User age'),
tags: z.array(z.string()).describe('User tags')
}),
output: z.object({
processed: z.boolean(),
data: z.record(z.unknown())
})
}, async (params) => {
// Automatic validation of inputs and outputs
return {
processed: true,
data: params
};
});2. With createTool() Helper
For advanced use cases with runtime validation:
import { createTool, z } from '@kadi.build/core';
const { definition, handler } = createTool({
name: 'convert',
description: 'Convert units',
input: z.object({
value: z.number(),
from: z.enum(['km', 'miles']),
to: z.enum(['km', 'miles'])
}),
output: z.object({
result: z.number(),
unit: z.string()
}),
handler: async ({ value, from, to }) => {
// Your logic here
return { result: value * 1.6, unit: to };
}
});
ability.registerTool(definition, handler);3. With JSON Schema (Backward Compatible)
Traditional approach still supported:
ability.registerTool({
name: 'greet',
description: 'Greet someone',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Name to greet' }
},
required: ['name']
},
outputSchema: {
type: 'object',
properties: {
greeting: { type: 'string' }
}
}
}, async ({ name }) => {
return { greeting: `Hello, ${name}!` };
});Migration from JSON Schema to Zod
Before (JSON Schema):
// 64 lines of boilerplate
ability.registerTool({
name: 'deployToAkash',
description: 'Deploy to Akash Network',
inputSchema: {
type: 'object',
properties: {
profile: {
type: 'string',
description: 'Deployment profile name'
},
dryRun: {
type: 'boolean',
description: 'Preview without deploying',
default: false
},
verbose: {
type: 'boolean',
description: 'Enable verbose output',
default: false
}
},
required: ['profile']
},
outputSchema: {
type: 'object',
properties: {
success: { type: 'boolean' },
dseq: { type: 'string' },
services: {
type: 'array',
items: { type: 'string' }
}
}
}
}, handler);After (Zod):
// 15 lines - clean and type-safe!
ability.registerTool({
name: 'deployToAkash',
description: 'Deploy to Akash Network',
input: z.object({
profile: z.string().describe('Deployment profile name'),
dryRun: z.boolean().default(false).describe('Preview without deploying'),
verbose: z.boolean().default(false).describe('Enable verbose output')
}),
output: z.object({
success: z.boolean(),
dseq: z.string(),
services: z.array(z.string())
})
}, handler);Result: 77% less code!
Transport Protocols
KADI supports three transport protocols for different use cases:
Native (In-Process)
const ability = await loadAbility('my-ability', 'native');
// Direct function calls, zero IPC overheadStdio (Child Process)
const ability = await loadAbility('my-ability', 'stdio');
// JSON-RPC over stdin/stdout, language-agnosticBroker (Distributed)
const ability = await loadAbility('my-ability', 'broker', {
brokerUrl: 'ws://localhost:8080',
networks: ['global']
});
// WebSocket-based distributed communicationEvents
Publish and subscribe to events across all protocols:
// Publishing events
ability.registerTool({
name: 'process',
input: z.object({ data: z.string() }),
output: z.object({ result: z.string() })
}, async (params) => {
// Publish progress events
await ability.publishEvent('process.started', { data: params.data });
const result = await doWork(params.data);
await ability.publishEvent('process.completed', { result });
return { result };
});
// Subscribing to events
ability.subscribeToEvent('process.*', (data) => {
console.log('Process event:', data);
});Broker Mode
Connect to KADI broker for distributed communication:
const client = new KadiClient({
name: 'my-agent',
role: 'agent',
brokers: {
dev: 'ws://localhost:8080',
prod: 'ws://prod.example.com:8080'
},
defaultBroker: 'dev',
networks: ['global']
});
// Register tools
client.registerTool({
name: 'greet',
input: z.object({ name: z.string() }),
output: z.object({ greeting: z.string() })
}, async ({ name }) => {
return { greeting: `Hello, ${name}!` };
});
// Connect to broker
await client.serve('broker');
// Call remote tools
const result = await client.callTool('translator', 'translate', {
text: 'Hello',
to: 'es'
});API Reference
KadiClient
Main class for all KADI operations:
const client = new KadiClient({
name: 'my-ability',
version: '1.0.0',
role: 'ability', // 'agent' or 'ability'
brokers: { /* broker configs */ },
defaultBroker: 'dev',
networks: ['global']
});Methods:
registerTool(definition, handler)- Register a toolserve(mode)- Start serving ('native', 'stdio', 'broker')callTool(agent, tool, params)- Call remote toolpublishEvent(name, data)- Publish eventsubscribeToEvent(pattern, callback)- Subscribe to eventsloadAbility(name, protocol, options)- Load another ability
loadAbility
Load an ability by name and protocol:
const ability = await loadAbility('ability-name', 'protocol', {
brokerUrl: 'ws://localhost:8080',
networks: ['global']
});createTool
Helper for creating tools with validation:
import { createTool, z } from '@kadi.build/core';
const { definition, handler } = createTool({
name: 'toolName',
input: z.object({ /* ... */ }),
output: z.object({ /* ... */ }),
handler: async (params) => { /* ... */ }
});Common Patterns
Error Handling
ability.registerTool({
name: 'riskyOperation',
input: z.object({ data: z.string() }),
output: z.object({
success: z.boolean(),
result: z.string().optional(),
error: z.string().optional()
})
}, async (params) => {
try {
const result = await performOperation(params.data);
return { success: true, result };
} catch (error) {
await ability.publishEvent('operation.error', {
error: error.message,
params
});
return { success: false, error: error.message };
}
});Health Check
ability.registerTool({
name: 'health',
input: z.object({}),
output: z.object({
status: z.string(),
uptime: z.number(),
memory: z.record(z.number())
})
}, async () => {
return {
status: 'healthy',
uptime: process.uptime(),
memory: process.memoryUsage()
};
});Environment Variables
# Protocol selection
KADI_PROTOCOL=stdio
# Broker configuration
KADI_BROKER_URL=ws://localhost:8080
KADI_AGENT_SCOPE=project-123Debug Mode
DEBUG=kadi:* node index.jsTroubleshooting
Broker Connection Failures
- Verify broker URL is correct
- Check network connectivity
- Ensure broker is running
Events Not Arriving
- Subscribe BEFORE triggering events
- Verify pattern matching
- Check that publisher and subscriber are on same network
Type Errors with Zod
- Ensure Zod schemas match handler types
- Use
z.infer<typeof schema>for TypeScript types - Check that all required fields are provided
License
MIT
Related Projects
- @kadi.build/cli - Command-line interface
- @kadi.build/broker - KADI broker
Built with ❤️ by the KADI team
