Record local tool calls and enqueue durable work.
TypeScript SDK
Install the published @getratchet/sdk package with npm install @getratchet/sdk. Version 0.1.0 requires Node.js 22 or later. You can also use the HTTP quickstart and API reference.
Create separate project and environment scoped INGEST and WORKER keys in Settings. Keep them on your server.
Record a local tool call
import { createRatchet } from '@getratchet/sdk';
const ratchet = createRatchet({
baseUrl: 'https://getratchet.app',
apiKey: process.env.GETRATCHET_INGEST_KEY!,
});
await ratchet.startRun('Customer onboarding');
const send = ratchet.wrap(sendWelcomeEmail, {
name: 'send_welcome_email', endpoint: 'Email service',
idempotencyKey: (input: { customerId: string }) => `welcome:${input.customerId}`,
});
await send({ customerId: 'cus_2048' });
await ratchet.finishRun();wrap() runs your function inside your process. It records attempts, but cannot reconstruct the function after a crash.
Enqueue durable work
import { createRatchet } from '@getratchet/sdk';
const ratchet = createRatchet({
baseUrl: 'https://getratchet.app',
apiKey: process.env.GETRATCHET_INGEST_KEY!,
});
await ratchet.startRun('Customer onboarding');
await ratchet.enqueue({ customerId: 'cus_2048' }, {
name: 'send_welcome_email', version: '1', endpoint: 'Email service',
idempotencyKey: 'welcome:cus_2048', timeoutMs: 30_000, maxAttempts: 5,
});
await ratchet.finishRun();Run a separate worker
import { createRatchet } from '@getratchet/sdk';
const worker = createRatchet({
baseUrl: 'https://getratchet.app',
apiKey: process.env.GETRATCHET_WORKER_KEY!,
});
worker.registerTool({
name: 'send_welcome_email', version: '1',
handler: async (input: { customerId: string }, { idempotencyKey, signal }) =>
sendWelcomeEmail(input, { idempotencyKey, signal }),
});
await worker.worker.start({ concurrency: 4, signal: shutdownSignal });Run the worker on infrastructure that remains active. Vercel hosts GetRatchet's API and console, not your handler. A missing exact name/version worker leaves the job queued. See worker operations for lease, retry, replay, and shutdown behavior. Durable execution is at least once, so the destination must deduplicate irreversible effects using the idempotency key.
Durable retry policies and error decisions
Durable jobs support STANDARD (5 attempts, 30s initial, 15m cap), AGGRESSIVE (8 attempts, 5s initial, 5m cap), RELAXED (3 attempts, 120s initial, 30m cap), and CUSTOM. Built-ins double their delay with ±20% jitter; CUSTOM supplies maxAttempts, initialDelayMs, multiplier, maxDelayMs, and jitterPercent. Counts include the first execution. Caps precede jitter; the final safety limit is 24 hours.
A selected tool contract overrides the endpoint policy. Explicit enqueue maxAttempts overrides only the attempt count. Each new job snapshots the complete policy; later endpoint edits or contract publication do not change its policy or saved due time. Existing jobs without snapshot data keep the old preset behavior. Synthetic tests remain one attempt.
TypeScript handlers can throw RetryableError(message, { retryAfterMs }) or NonRetryableError(message) and register classifyError(error, context) for third-party failures. Python provides RetryableError(message, retry_after_ms=...), NonRetryableError, and classify_error. Unknown errors default to retryable; schema failures and cancellation remain non-retryable. A classifier failure is reported only to the local error callback and falls back to retryable.
Retry hints must be integer milliseconds from 1,000 to 86,400,000. The persisted delay is the greater of the normal jittered policy delay and the hint, capped at 24 hours; the hint itself is never jittered. An open circuit, pause, concurrency gate or attempt limit is never bypassed. Error objects, stacks and classifier metadata are not sent to the API.
Execution is at least once: a crash or lost report can repeat a completed side effect. Pass the stable job idempotency key to the destination and require destination-side deduplication for irreversible writes.
See custom policies and provider examples for endpoint/tool publication, validation limits, HTTP 429 with Retry-After, HTTP 503, non-retryable HTTP 400 validation failures, and unknown-error fallback.