Run Workforce agents
from your own code.
A REST API, a TypeScript SDK and a starter project for calling eClips Workforce from your systems. Start a run, wait for the result, and handle the ones that need a person.
The public API is included on the Growth and Enterprise plans. The SDK and CLI aren't on the public npm registry yet; ask us for access.
Your first run, in four steps.
npm install @eclips/sdkStart from a working project.
The CLI asks for a project name, a template and, if you have it, your API key. Then it writes a project you can install and run.
express-apiAn Express server with a /run endpointnextjs-dashboardA Next.js page that lists run historyagent-onlyOne TypeScript script, no servernpx create-eclips-appRequires Node.js 18 or newer.
Hear about a run when it finishes.
Register a webhook and eClips POSTs to it when a run completes, fails or needs a person. Each POST carries an X-eClips-Signature header, an HMAC-SHA256 of the body made with the secret you got at registration, so you can check it came from us.
import crypto from 'crypto';
import { EClipsClient } from '@eclips/sdk';
const client = new EClipsClient({ apiKey: process.env.ECLIPS_API_KEY! });
// Register a webhook. The signing secret is returned once, so store it.
const { secret } = await client.createWebhook(
'https://your-app.com/webhooks/eclips',
['run.completed', 'run.failed', 'run.triage_required'],
);
// Verify the request came from eClips
function verifySignature(rawBody: string, secret: string, sig: string) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return `sha256=${expected}` === sig;
}
// Express handler
app.post('/webhooks/eclips', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.headers['x-eclips-signature'] as string;
if (!verifySignature(req.body.toString(), process.env.WEBHOOK_SECRET!, sig)) {
return res.status(401).send('Unauthorized');
}
const event = JSON.parse(req.body.toString());
switch (event.event) {
case 'run.completed':
console.log('Run finished:', event.run_id, event.data.output);
break;
case 'run.failed':
console.error('Run failed:', event.run_id, event.data.error);
break;
case 'run.triage_required':
// Notify Slack, email the team, etc.
break;
}
res.json({ ok: true });
});Delivered events
run.completedAgent finished successfully
run.failedAgent run encountered an error
run.triage_requiredAgent needs human review
Run one agent over a whole list.
Send up to 500 inputs in one call with createBatch, then poll for progress. Rows run 10 at a time, and one failed row doesn't stop the rest.
One call, up to 500 rows
POST /v1/batches with a list of inputs for the same agent
Progress counts
getBatch returns completed, failed and total rows
Cancellable
cancelBatch stops an in-flight batch at any time
Listable
listBatches returns the batch history for your org
// Run the same agent over many rows in one call
const batch = await client.createBatch('ap_specialist', [
{ invoice_id: 'INV-1001' },
{ invoice_id: 'INV-1002' },
{ invoice_id: 'INV-1003' },
]);
// Poll for progress, or cancel if needed
const status = await client.getBatch(batch.id);
console.log(status.completed, '/', status.total);The SDK methods.
Every method is typed. The API reference covers parameters, errors and rate limits.
client.run()RunsTrigger an agent run, returns run_id immediately
client.runAndWait()RunsTrigger + poll until terminal
client.waitForRun()RunsPoll an existing run until terminal
client.getRun()RunsFetch a single run by id
client.listRuns()RunsRun history ({ data, total, limit, offset })
client.listTriage()TriagePending human-in-the-loop items
client.approveTriage()TriageApprove and continue the blocked run
client.rejectTriage()TriageReject an item with an optional reason
client.createWebhook()WebhooksRegister a URL + events; returns the secret once
client.listWebhooks()WebhooksList registered webhook endpoints
client.deleteWebhook()WebhooksDelete a webhook by id
client.createBatch()BatchRun an agent over many rows at once
client.getBatch()BatchFetch a batch with progress counts
client.listBatches()BatchList batches for your org
client.cancelBatch()BatchCancel an in-flight batch
Error handling
Each kind of failure has its own error class, so you handle the ones you care about.
import {
EClipsClient,
AuthenticationError,
RateLimitError,
ValidationError,
NotFoundError,
TimeoutError,
} from '@eclips/sdk';
try {
const result = await client.runAndWait('ap_specialist', task);
} catch (err) {
if (err instanceof AuthenticationError) {
// Invalid or missing API key
} else if (err instanceof RateLimitError) {
// err.retryAfter is the wait in seconds
await sleep(err.retryAfter ?? 60);
} else if (err instanceof TimeoutError) {
// The wait timed out, but the run carries on.
// Poll client.getRun(err.runId) to check progress.
} else if (err instanceof NotFoundError) {
// Run, triage item, or webhook not found
}
}Start with
one problem.
Tell us where the work gets stuck, whether it's a spreadsheet at month-end or an ISO 9001 audit on the calendar. We'll show you the product that fits, or tell you if none of ours does.
A 30-minute live walkthrough. No slides.