Official TypeScript / JavaScript SDK for the Coherence API — records, modules, search, activity, and agents. Fully typed, zero runtime dependencies, ESM + CommonJS.
npm install @coherenceos/sdkRequires Node 18+ (uses the built-in fetch).
import { CoherenceClient } from '@coherenceos/sdk';
const coherence = new CoherenceClient({ apiKey: process.env.COHERENCE_API_KEY! });
// Who am I?
const me = await coherence.me();
// List and create records
const { records, total } = await coherence.records.list('contacts', { pageSize: 50 });
const contact = await coherence.records.create('contacts', {
displayName: 'Jane Doe',
fields: { email: 'jane@example.com', status: 'active' },
});
// Cross-module search
const hits = await coherence.search({ query: 'acme', limit: 10 });Create an API key at Settings → API Keys. Keys use the sk_live_ prefix and may be scoped (workspace:read, records:read, records:write, agents:write).
Send a message to your Coherence agent (Nash by default) and await the final reply:
const result = await coherence.agents.message({
message: "Draft a follow-up to this week's leads.",
});
console.log(result.response);Or stream the run as it happens:
for await (const event of coherence.agents.stream({ message: 'Summarize my pipeline' })) {
if (event.type === 'token') process.stdout.write(event.text);
else if (event.type === 'tool_call') console.error(`\n[${event.label}]`);
else if (event.type === 'done') console.error(`\n(done in ${event.durationMs}ms)`);
}Non-2xx responses throw a CoherenceError carrying the machine-readable code:
import { CoherenceError } from '@coherenceos/sdk';
try {
await coherence.records.get('contacts', 'missing-id');
} catch (err) {
if (err instanceof CoherenceError) {
console.error(err.code, err.statusCode); // e.g. "not_found" 404
if (err.isRetryable) {
// 429 / 5xx — back off (err.retryAfter is set on 429 when the server sends Retry-After)
}
}
}new CoherenceClient({
apiKey: 'sk_live_...',
baseUrl: 'https://api.getcoherence.io/v1', // default
timeoutMs: 60_000, // per-request; 0 disables. Streams are exempt.
fetch: customFetch, // optional custom fetch
});Every method accepts an optional trailing AbortSignal.
me() · search() · openapi() · modules.{list,get,fields,views} · records.{list,get,create,update,delete,bulkUpdate,bulkDelete} · references.{list,linkedIds,picker} · activity.{workspace,module,record} · agents.{message,stream}
Richer operations — sending email, scheduling outreach, posting to social — run through agents.message / agents.stream, governed by your workspace's approval rules.
MIT