Quickstart — agent in 5 minutes
Register a JECP agent, get 100 free calls, and invoke a capability with the TypeScript SDK.
Prerequisites
- Node.js ≥ 20
- 5 minutes
1. Install the SDK
npm install @jecpdev/sdk
2. Register an agent
import { JecpClient } from '@jecpdev/sdk';
const reg = await JecpClient.register({
name: 'MyResearchAgent',
agent_type: 'research',
description: 'Reads docs, writes summaries',
});
console.log('agent_id:', reg.agent_id);
console.log('api_key: ', reg.api_key); // shown ONCE — save it
console.log('free calls:', reg.free_calls_remaining); // 100
Save the api_key now. Treat it like a Stripe secret. It cannot be recovered if lost — you'd register a new agent and start over.
3. Invoke a capability
const jecp = new JecpClient({
agentId: reg.agent_id,
apiKey: reg.api_key,
});
const { output, billing, wallet_balance_after } = await jecp.invoke(
'jobdonebot/content-factory',
'translate',
{ text: 'Hello, world!', target_lang: 'JA' },
);
console.log(output); // { translated: 'こんにちは、世界!' }
console.log(billing.charged); // true
console.log(billing.amount_usdc); // 0.005
console.log(wallet_balance_after); // 0.995 (started 1.00, charged 0.005)
What just happened
- Register: Hub created an
agent_id+api_keypair, allocated 100 free calls. - Invoke: Hub validated credentials, looked up the
jobdonebot/content-factorymanifest, found thetranslateaction, charged$0.005from your wallet, signed the request with HMAC, forwarded to the Provider's endpoint, and returned the result. - Billing: 85% to Provider, 10% Hub fee, 5% payment processing — atomic in a single SQL transaction.
Production-grade defaults
const jecp = new JecpClient({
agentId, apiKey,
timeoutMs: 30_000,
retryConfig: { maxRetries: 3 }, // exp backoff on 5xx/408/429/network
logger: console, // observe retries and errors
});
// Cancel mid-flight + per-call timeout
const ctl = new AbortController();
const r = await jecp.invoke('a/b', 'c', input, {
signal: ctl.signal,
timeoutMs: 60_000,
mandate: { budget_usdc: 1.00 }, // pre-authorize spend cap
});
Error handling with next_action
import { JecpError, InsufficientBalanceError } from '@jecpdev/sdk';
try {
await jecp.invoke('a/b', 'c', input);
} catch (e) {
if (e instanceof InsufficientBalanceError) {
// Auto-recovery — open the topup URL
const { url } = await jecp.topup(20);
console.log('Top up here:', url);
}
if (e instanceof JecpError) {
console.log('next_action:', e.nextAction);
}
}