oceum
v0.6.0
Published
Official SDK for Oceum — governed agent infrastructure. Progressive autonomy, blind-relay vault (the agent never sees the secret), governed execution, and enterprise-grade observability.
Maintainers
Readme
oceum
Official SDK for Oceum — governed agent infrastructure. Progressive autonomy, blind-relay vault (the agent never sees the secret), governed execution, and enterprise-grade observability.
Zero dependencies. Works with Node.js 18+, Deno, and Bun.
Install
npm install oceumQuick Start
const { Oceum } = require('oceum');
const client = new Oceum({
apiKey: process.env.OCEUM_API_KEY, // oc_xxx
agentId: process.env.OCEUM_AGENT_ID, // agt_xxx
});
// Start auto-heartbeat (every 60s)
client.startHeartbeat();
// Wrap tasks with automatic logging
const result = await client.wrap('Process leads', async () => {
const leads = await fetchLeads();
await processAll(leads);
return leads.length;
});
// Report LLM usage for cost tracking
await client.reportUsage({
model: 'claude-sonnet',
tokensInput: 1200,
tokensOutput: 450,
});
// Clean up
client.stopHeartbeat();
await client.setStatus('idle');Governance — the front door
Before an agent takes an action, ask Oceum whether it's allowed. Low-risk actions clear instantly; consequential ones are held for a human's approval — and every decision is written to a sealed audit record.
const { Oceum } = require('oceum');
const oceum = new Oceum({ apiKey: process.env.OCEUM_API_KEY, agentId: process.env.OCEUM_AGENT_ID });
// 1. Ask before acting
const decision = await oceum.check('delete_customer', { target: 'accounts/941' });
if (decision.allowed) {
// Low-risk — proceed immediately
await deleteCustomer('accounts/941');
await oceum.reportOutcome(decision.executionId, { status: 'success' });
} else {
// Held for a human — a person is notified the moment it lands.
const resolved = await oceum.waitForApproval(decision.executionId);
if (resolved.execution.status === 'approved') {
await deleteCustomer('accounts/941');
await oceum.reportOutcome(decision.executionId, { status: 'success' });
}
}check() returns { allowed, executionId, mode, reason?, pollUrl? }. When mode is 'approval_required', the action waits for a human — poll getExecution(executionId) yourself, or await waitForApproval(executionId) (throws OceumError with status 408 if it times out).
No SDK? No Problem
Oceum is just HTTP. Any language, any framework — POST JSON to the webhook endpoint:
# Heartbeat
curl -X POST https://oceum.ai/api/webhook \
-H "Authorization: Bearer $OCEUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event":"heartbeat","agentId":"agt_xxx"}'
# Report a completed task
curl -X POST https://oceum.ai/api/webhook \
-H "Authorization: Bearer $OCEUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event":"task_complete","agentId":"agt_xxx","data":{"taskName":"sync-orders"}}'
# Report LLM usage
curl -X POST https://oceum.ai/api/webhook \
-H "Authorization: Bearer $OCEUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"event":"usage","agentId":"agt_xxx","data":{"model":"gpt-4o","tokensInput":500,"tokensOutput":200}}'Python:
import requests
API_KEY = "oc_xxx"
AGENT_ID = "agt_xxx"
requests.post("https://oceum.ai/api/webhook",
headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
json={"event": "heartbeat", "agentId": AGENT_ID}
)API
| Method | Description |
|--------|-------------|
| check(action, opts?) | Ask before acting — returns { allowed, executionId, mode } |
| getExecution(id) | Fetch a governed execution's current state |
| waitForApproval(id, opts?) | Poll until a held action is approved or rejected |
| reportOutcome(id, outcome) | Record what happened after you execute |
| register(opts) | Register a framework + its agents with governance |
| heartbeat() | Send keep-alive, sets status to active |
| taskStart(name, meta?) | Log task initiation |
| taskComplete(name, meta?) | Log task completion, increments count |
| error(name, opts?) | Log error, { fatal: true } sets error status |
| warning(msg, meta?) | Log non-critical warning |
| setStatus(status) | Set status: active, idle, paused, offline, error |
| startHeartbeat(ms?) | Auto-heartbeat every N ms (default: 60s) |
| stopHeartbeat() | Stop auto-heartbeat |
| wrap(name, fn, meta?) | Auto start/complete/error around async fn |
| reportUsage(opts?) | Report LLM token usage for cost tracking |
| memory(content, opts?) | Write shared memory visible to peer agents |
| readMemory(opts?) | Read shared memory entries |
| vaultStore(data, opts?) | Store sensitive data, returns vault token |
| vaultRetrieve(token) | Retrieve data using vault token |
| vaultProxy(token, req) | Zero-knowledge API call with vault credential |
| vaultRevoke(token) | Permanently revoke a vault token |
| vaultList(opts?) | List vault tokens (metadata only) |
Platform Capabilities
The Oceum platform (which this SDK connects to) includes:
- Governed Execution Engine -- Job queue with credential injection, approval workflows, and full audit trail
- Protocol Adapters -- REST, SOAP (WS-Security), SFTP, and JDBC adapters for legacy system integration
- Data Mapping -- Canonical business object translation between legacy formats
- 28 OAuth Integrations -- Pre-built connectors for Slack, Google, Salesforce, Stripe, and more
Agents interact with these capabilities through the webhook API. See oceum.ai/docs-public for full platform documentation.
Cost Tracking
Report LLM token usage per call. Oceum calculates cost using configurable model pricing and enforces budget caps automatically.
// After an LLM call
await client.reportUsage({
model: 'claude-haiku',
tokensInput: 800,
tokensOutput: 200,
});
// Or include usage in task_complete meta for automatic tracking
await client.taskComplete('generate-report', {
usage: { model: 'gpt-4o', tokensInput: 2000, tokensOutput: 1500 }
});Budget caps, alert thresholds, and per-model pricing are configured in the Oceum dashboard under Settings > Cost Controls.
Error Handling
const { Oceum, OceumError } = require('oceum');
try {
await client.heartbeat();
} catch (err) {
if (err instanceof OceumError) {
console.log(err.statusCode); // 401, 404, etc.
console.log(err.body); // API response
}
}Optimistic Concurrency (v0.5.0)
Avoid silently overwriting fresher state when two writers race for the same row.
When to use
- You read a vault entry, present it to the user for editing, and want to make sure no other process modified it before the user submits.
- Your agent reads a memory entry, derives a decision, and writes back — and another agent might be doing the same thing concurrently.
- You're updating an integration's config and another admin might be doing the same in another tab.
Pattern
const { Oceum, OceumConflictError } = require('oceum');
const oceum = new Oceum({ apiKey: 'oc_xxx', agentId: 'agt_xxx' });
// 1. Read with hash
const { data, hash } = await oceum.vaultReadWithHash('vtk_xxx');
// 2. Modify
const newPayload = { label: 'Updated label' };
// 3. Write expecting the original hash
try {
const { hash: newHash } = await oceum.vaultWriteExpecting('vtk_xxx', hash, newPayload);
console.log('Saved. New hash:', newHash);
} catch (err) {
if (err instanceof OceumConflictError) {
// Another writer beat you to it. err.current is the latest server state.
console.warn('Conflict! Server has:', err.current);
// Re-read, merge, retry — or surface to the user.
} else {
throw err;
}
}Same pattern for memory and integrations:
oceum.memoryReadWithHash(memoryId)/oceum.memoryWriteExpecting(memoryId, hash, payload)oceum.integrationReadWithHash(integrationId)/oceum.integrationWriteExpecting(integrationId, hash, payload)
Important notes
- Do NOT use on memory rows whose name starts with
pulse-— those are system-internal upserts and may cause spurious 409s. - The SDK does NOT auto-retry on 409 — re-attempting with the same stale hash would just 409 again. Caller must re-read first.
- 5xx errors and network errors retry as before (exponential backoff, MAX_RETRIES=3).
- The SDK sends
If-Match: <hash>HTTP header — RFC 7232 standard. Server returns the new hash in the response body and as anETagheader.
Webhook Verification
Verify incoming webhook signatures with HMAC-SHA256:
const valid = Oceum.verifyWebhookSignature(rawBody, signature, secret);Docs
Full documentation: oceum.ai/docs-public
License
MIT
