Skip to content

Other frameworks

Three ways in, from least to most work.

If your stack already exports OpenTelemetry or OpenInference spans, you can read them in the GraphMind viewer today:

Terminal window
graphmind import trace.json

Accepted inputs:

  • OTLP/JSON — the OTel collector file exporter, or SDK JSON exporters.
  • Flat span lists — OpenInference / Arize Phoenix-style JSON or JSONL.

Recognised span dialects: Vercel AI SDK OTel spans, OTel GenAI semantic conventions, and OpenInference. Unrecognised spans are imported as generic nodes or skipped with a note. The command prints a summary — nodes, errors, duration, skipped spans — and a viewer deep link.

For a framework GraphMind has no adapter for, you can drive the runtime directly. @graphmind-ai/client owns the session, the transport, the ring buffer and the gate engine — you only supply the events and the awaits.

import { createSession } from '@graphmind-ai/client';
const session = createSession({
appName: 'my-framework-app',
sdk: { name: 'my-framework', version: '1.2.3' },
});
await session.ready();
await session.run('nightly-report', async (ctx) => {
const nodeId = 'tool:fetchMetrics';
const instanceId = 'call-1';
session.emit('node.started', {
nodeId,
kind: 'tool',
name: 'fetchMetrics',
instanceId,
input: { range: '7d' },
});
const decision = await session.gate('before', { nodeId, kind: 'tool', name: 'fetchMetrics' });
if (decision.action === 'inject') return decision.output; // skip execution
if (decision.action === 'abort') throw ctx.signal.reason; // cooperative cancel
const started = Date.now();
try {
const output = await fetchMetrics({ range: '7d' }, { signal: ctx.signal });
session.emit('node.finished', {
nodeId,
instanceId,
output,
durationMs: Date.now() - started,
status: 'ok',
});
return output;
} catch (error) {
session.emit('node.error', { nodeId, instanceId, error: toErrorInfo(error) });
const onError = await session.gate('error', { nodeId, kind: 'tool', name: 'fetchMetrics' });
if (onError.action === 'inject') return onError.output;
throw error;
}
});
await session.dispose();

That is roughly what every adapter does; the work in a real adapter is finding the right hook points and mapping the framework’s shapes onto the schema, not the GraphMind plumbing.

Adapters are how the project scales past what one maintainer can cover, and the protocol is deliberately small enough to make that realistic — nine event types, four control types, one WebSocket.

Adapters in other languages target the wire protocol directly — @graphmind-ai/schema ships a JSON Schema export of the envelope for exactly that purpose.