Server SDK
Read and write Durable Objects from your Node.js backend.
Writes to Durable Objects come from your server, using
pingerchips-js-server.
The Python SDK is agent-only today — it does not include a Durable Objects client. Use the HTTP API from Python for now.
Setup
npm install pingerchips-js-serverimport PingerchipsServer from 'pingerchips-js-server';
const pc = new PingerchipsServer(
process.env.PINGERCHIPS_APP_KEY,
process.env.PINGERCHIPS_APP_SECRET,
{ endpoint: 'https://queue.pingerchips.com' } // optional; this is the default
);The constructor takes (appKey, appSecret, options?) positionally. The host
option is endpoint, not host.
Get an object handle
const order = pc.object('order', 'order-42');Lightweight — no network call. Every method below issues one HTTP request with
X-App-Key + X-App-Secret headers (see
Authentication).
Reading
object.state()
Full state map plus the current log_id.
const s = await order.state();
// { status: "processing", assigned_to: "agent-7", retry_count: 2, log_id: 17 }object.get(slot)
One slot's value (or null if unset). Takes a single argument — there is no
default parameter.
const status = await order.get('status'); // "processing"Writing
Each write resolves to the raw server response — { log_id }, plus value
for increment.
object.set(slot, value)
await order.set('status', 'shipped'); // { log_id: 18 }object.setAll(map)
Atomic multi-slot write — one log entry, one batch event.
await order.setAll({
status: 'shipped',
shipped_at: Date.now(),
});object.increment(slot, by = 1)
Atomic. Unset slot starts at 0.
await order.increment('retry_count'); // { log_id: 20, value: 3 }
await order.increment('score', 10); // { log_id: 21, value: <prev + 10> }object.append(slot, value)
Appends one item to a list slot (initialised to [] if unset).
await order.append('history', {
event: 'shipped',
at: Date.now(),
});object.delete(slot)
await order.delete('temp_lock');object.transaction(ops)
Atomic multi-operation write. ops is an array, not a callback:
await order.transaction([
{ op: 'set', key: 'status', value: 'shipped' },
{ op: 'increment', key: 'retry_count', by: 1 },
{ op: 'append', key: 'history', value: { event: 'shipped' } },
{ op: 'delete', key: 'temp_lock' },
]);
// { log_id: 24 }Valid ops: set, delete, increment, append. All commit together or none
do.
There is no get op — the transaction cannot read. For conditional
read-modify-write ("only ship if currently processing"), do a
GET / state() first, decide in your code, then send the transaction.
Because writes on one object are linearised server-side, a stale read window is
the only race, and it is small.
object.purge()
Permanently deletes the object.
await order.purge(); // resolves to null (HTTP 204)Replay the log
const entries = await order.log(17); // entries with log_id > 17
// [ { op: "set", key: "status", value: "shipped", log_id: 18 }, ... ]afterId defaults to 0.
Agentic workflow pattern
Durable Objects give a multi-agent pipeline one serialised, persistent working memory:
async function runAgent(runId, agentId, pipeline) {
const run = pc.object('run', runId);
for (const step of pipeline) {
const result = await step.execute();
await run.append('steps', {
agent: agentId,
step: step.name,
result,
at: Date.now(),
});
await run.set(`status_${agentId}`, step.name);
}
await run.set(`status_${agentId}`, 'done');
}A client or orchestrator subscribed to the object sees every append and set
in real time — no polling.
Browser subscriptions
Mint a capability token for a browser client with
authenticateObject (pingerchips-js-server >= 3.0.0):
app.post('/auth/durable', (req, res) => {
const { socket_id, object_type, object_key } = req.body;
// your authorization check …
res.json(pc.authenticateObject(socket_id, object_type, object_key));
});The browser then subscribes with pingerchips.object(type, key) — see the
Client SDK.
Not yet available
object.subscribe()— a server-side real-time subscription to an object. Subscribe to thedurable:{appKey}:{type}:{key}channel directly for now.