Skip to Content
Sarek AI AccountabilitySDK Reference: TypeScript

Sarek AI Accountability TypeScript SDK

TypeScript SDK for accountable AI. Wraps your AI client, logs every call as a signed entry, and anchors a proof per decision. ESM, Node.js 18 or later.

npm install @sarek/ai-accountability

AiLogger.init()

Creates a logger instance. Loads or creates the agent identity (a P-256 key pair on disk) and ensures the local directory structure exists.

Signature

class AiLogger { static init(options?: AiLoggerOptions): Promise<AiLogger> }

Parameters

NameTypeDefaultDescription
options.namestring'default'Agent name. One identity and log file per name.
options.rolestring'unspecified'The agent’s role, recorded in every entry.
options.ledgerUrlstringsee belowCore Service endpoint.
options.onLog(entry: LogEntry, proof: AiLoggerProof) => voidCalled immediately after signing.
options.onStamped(proof: AiLoggerProof) => voidCalled when the proof is anchored (~10 s later).

URL precedence: explicit ledgerUrl, then ai-accountability/config.json (created automatically, default http://localhost:3000), then the built-in fallback.

Returns

Promise<AiLogger>.

Example

import { AiLogger } from '@sarek/ai-accountability' const sarek = await AiLogger.init({ name: 'claims-triage', role: 'insurance-claims', onLog: (entry, proof) => auditDb.insert(entry), onStamped: proof => auditDb.attachProof(proof.logId, proof.txHash) })

monitor()

Wraps an AI client in a Proxy and returns the wrapper. The original client is never mutated. Provider detection is duck-typed from the client object, so no provider SDK becomes a dependency.

Signature

monitor(client: unknown, options?: MonitorOptions): unknown

Parameters

NameTypeDescription
clientunknownThe AI client to wrap.
options.providerstringRequired only for clients that cannot be distinguished automatically.

Returns

A wrapped client with the same API as the original. Each response carries the proof at response.aiLogger.

Supported providers

ProviderDetection
OpenAI, Anthropic, Gemini, Azure OpenAI, Ollama (native), AWS Bedrock (Converse), Mistral, Cohere (V2)Automatic
Groq, Together AI, OpenRouterAutomatic with the official SDK; hint when using an OpenAI client against their endpoint
Perplexity, FireworksHint: { provider: 'perplexity' } / { provider: 'fireworks' } (no official TypeScript SDK)
xAI (Grok)Hint: { provider: 'xai' } (wire-identical to OpenAI)

Example

import OpenAI from 'openai' import Anthropic from '@anthropic-ai/sdk' const openai = sarek.monitor(new OpenAI()) const anthropic = sarek.monitor(new Anthropic())

Errors

Throws if the client cannot be recognized and no provider hint is given.

close()

Waits for all in-flight anchoring to finish. Call it before process exit so no proofs are lost. Safe to call more than once.

Signature

close(): Promise<void>

Example

await sarek.close()

The log flow

  1. Input and output are hashed separately with SHA3-256. Objects are serialized canonically (compact JSON, keys sorted at every level), so the same call produces the same hashes in TypeScript and Python.
  2. The entry is signed with the agent’s P-256 key.
  3. onLog(entry, proof) fires immediately. The AI response is already on its way back to your code.
  4. The combined hash is anchored asynchronously (~10 s). Failures are logged and never thrown into your application.
  5. The proof file is written, the log line is updated with txHash and blockNumber, and onStamped(proof) fires.

LogEntry

One entry per AI call, appended to ai-accountability/logs/<agent>.jsonl.

FieldTypeDescription
logIdstringUUID, unique per call
timestampstringISO 8601
providerstringOne of the 14 supported providers
modelstringModel identifier from the response
inputHashstringSHA3-256 of the input, never the raw prompt
outputHashstringSHA3-256 of the output, never the raw completion
predictionIdstringProvider response id, or a generated UUID
inputTokensnumberFrom the provider’s usage block
outputTokensnumberFrom the provider’s usage block
totalTokensnumberSummed when the provider does not return it
latencyMsnumberWall-clock latency of the call
finishReasonstring | nullWhy the model stopped
statusCodenumberAlways 200; failed calls are not logged
systemFingerprintstring | nullExact model version where the provider exposes it
environmentstring | nullFrom process.env.NODE_ENV
sdkVersionstringSDK version that wrote the entry
agentIdstringThe agent name
rolestringThe agent role
signaturestringECDSA P-256 over inputHash + outputHash
txHashstringFilled in after anchoring
blockNumbernumberFilled in after anchoring
citationsstring[] | nullPerplexity only: source URIs, null otherwise

AiLoggerProof

Attached to every response as response.aiLogger and passed to both callbacks.

interface AiLoggerProof { logId: string agentId: string role: string inputHash: string outputHash: string ldgp: string // base64-encoded proof file txHash: string blockNumber: number proofPath: string // path to the .ldgp file on disk }

CLI

The package installs a sarek binary for working with local logs.

CommandDescription
sarek list [--agent <name>]List log entries, with anchoring status and txHash
sarek verify --logId <id>Show the entry and check that its proof file exists locally. Full cryptographic verification runs through the Core Service, see Verification.
sarek get log --logId <id>Extract entry plus proof to ai-accountability/extracted/<logId>/, a portable evidence package
sarek get report [--agent <name>]Generate a six-page PDF report and anchor it
sarek clear [--agent <name>]Delete local logs, proofs and reports

Local files

ai-accountability/ config.json created automatically .gitignore created automatically, protects private keys agents/ <name>/ identity.json private.key P-256 private key (chmod 600) logs/ <name>.jsonl one line per AI call proofs/ <name>/ log-<logId>.ldgp one proof per call reports/ written by `sarek get report` extracted/ written by `sarek get log`
Last updated on