Skip to content

Cross-Agent Context Sharing

SQLite-backed context sharing between agents with versioning, channels, encryption, and pub/sub transport.

When multiple agents work on the same project, they need to share decisions, assumptions, and constraints. Nella’s context sharing system provides a SQLite-backed store with versioning, channels, visibility controls, and real-time pub/sub — so agents stay coordinated without stepping on each other.

How It Works

  1. Agent A publishes a decision: “Using JWT with RS256 for API auth”
  2. Agent B queries the context channel and sees the decision before writing auth code
  3. If Agent B tries to contradict the decision, Nella flags the conflict
import { createContextManager } from '@usenella/core';

const ctx = createContextManager({
  workspaceId: 'my-project',
  agentId: 'agent-alpha',
  transport: 'local', // or 'supabase' for cross-machine
});

// Share a decision
await ctx.setDecision('jwt-auth', 'Use JWT with RS256 for all API endpoints');

// Another agent reads it
const decisions = await ctx.getDecisions();
// → [{ key: 'jwt-auth', value: 'Use JWT with RS256...', sourceAgentId: 'agent-alpha' }]

Context Types

Every context entry has a type that determines how it’s used:

TypeDescriptionExample
stringFree-form textNotes, comments
numberNumeric valueVersion numbers, thresholds
booleanFlagFeature toggles
objectStructured dataConfiguration objects
arrayList dataFile lists, dependency lists
codeCode snippetImplementation references
snippetShort code excerptPattern examples
decisionArchitectural decision”Use PostgreSQL over MySQL”
dependencyDependency info”Requires zod ^3.22”
preferenceCoding preference”Use early returns”

Convenience Methods

// Type-specific setters
await ctx.setSnippet('auth-pattern', 'const token = jwt.sign(...)');
await ctx.setDecision('db-choice', 'PostgreSQL for JSONB support');
await ctx.setDependency('zod', '{ version: "^3.22", reason: "Schema validation" }');
await ctx.setPreference('error-handling', 'Use Result types over try/catch');

// Type-specific getters
const snippets = await ctx.getSnippets();
const decisions = await ctx.getDecisions();
const dependencies = await ctx.getDependencies();

Visibility Levels

Control who can see each context entry:

LevelScopeUse Case
privateOnly the publishing agentInternal working notes
workspaceAll agents in the workspaceProject-level decisions
sharedAll agents on the channelCross-team coordination
globalAll agents everywhereOrganization-wide standards

Channels

Channels partition context into logical groups. Each channel has its own settings:

// Create a channel
await ctx.createChannel({
  name: 'backend-team',
  description: 'Backend API development context',
  allowedAgents: ['agent-alpha', 'agent-beta'],
  settings: {
    maxEntries: 1000, // Max entries per channel
    defaultTtl: 3600, // Default TTL in seconds (0 = no expiry)
    autoCleanup: true, // Remove expired entries automatically
  },
});

// Publish to a channel
await ctx.set('rate-limit-decision', 'Token bucket at 100 req/min', {
  type: 'decision',
  channel: 'backend-team',
  visibility: 'shared',
});

// Query a channel
const entries = await ctx.query({
  channelId: 'backend-team',
  types: ['decision', 'dependency'],
  limit: 20,
});

Versioning

Every update creates a new version. You can inspect history and roll back:

// Get version history
const versions = await ctx.getVersions('jwt-auth');
// → [{ version: 3, value: '...', updatedAt: '...' }, ...]

// Rollback to a previous version
await ctx.rollback('jwt-auth', 1); // Roll back to version 1
  • Max versions: 50 per entry (configurable)
  • Pruning: Oldest versions are automatically pruned when the limit is reached

Optimistic Concurrency

Context entries use ETags (SHA-256 of the serialized value) for conflict detection:

try {
  await ctx.set('api-design', 'REST with versioned paths', { etag: 'abc123' });
} catch (err) {
  if (err instanceof ContextConflictError) {
    // Another agent updated this entry since you last read it
    const latest = await ctx.get('api-design');
    // Resolve conflict and retry...
  }
}

Three search modes for finding context entries:

ModeDescriptionUse Case
substringCase-insensitive LIKE searchExact phrase matching
regexRegular expression matchingPattern matching
fuzzyJaro-Winkler similarity (threshold: 0.8)Typo-tolerant search
const results = await ctx.search('authentication', { mode: 'fuzzy' });

Encryption

Sensitive context entries can be encrypted at rest using AES-256-GCM:

await ctx.set('api-secret', 'sk_live_abc123', {
  encrypted: true,
});
// Stored as: iv:authTag:encryptedData (base64)

Transport Layer

The pub/sub system supports pluggable transports:

Local Transport (default)

In-process Map<channel, Set<handler>>. Best for single-machine setups where multiple agents run in the same process or connect via MCP.

Supabase Transport

Uses Supabase Realtime broadcast for cross-machine context sharing. Agents on different machines can share context in real-time.

const ctx = createContextManager({
  workspaceId: 'my-project',
  agentId: 'agent-remote',
  transport: 'supabase',
  supabaseUrl: process.env.SUPABASE_URL,
  supabaseKey: process.env.SUPABASE_KEY,
});

Database

Context is stored in SQLite (via better-sqlite3) with WAL mode for concurrent reads:

  • Tables: context_entries, context_versions, context_channels, context_meta
  • Indexes: 7 covering workspace_id, key, channel_id, expires_at, type, entry_id
  • Prepared statements: 18 pre-compiled for performance

MCP Integration

The shipped @getnella/mcp package exposes session-oriented context tools, not the full channel publishing surface from the core library.

Today the public MCP surface includes:

  • nella_get_context — Inspect the current session context, assumptions, dependency snapshot, and trust-chain challenge
  • nella_add_assumption — Record an assumption during the current task
  • nella_check_assumptions — Review assumption validity
  • nella_check_dependencies — Detect dependency drift

If you need multi-agent channel publishing, use SharedContextManager programmatically from @usenella/core in your own runtime. See the MCP Tools Overview for the shipped tool reference.

Events

The context manager emits 11 event types for real-time monitoring:

EventDescription
entry:createdNew context entry added
entry:updatedContext entry modified
entry:deletedContext entry removed
entry:expiredTTL reached, entry cleaned up
entry:expiringWarning: entry expires in < 60 seconds
version:createdNew version snapshot saved
version:prunedOld versions pruned past limit
channel:createdNew channel created
channel:deletedChannel removed
conflict:detectedOptimistic concurrency conflict
transport:errorPub/sub transport failure

Import / Export

Context snapshots can be exported and imported for workspace migration:

// Export everything
const snapshot = await ctx.export();
// { entries, versions, channels, schemaPatterns }

// Import with merge strategy
await ctx.import(snapshot, { strategy: 'merge' });
// Strategies: 'merge' | 'replace' | 'skip-existing'

Tip

Combine context sharing with Cloud Sync to persist context across machines automatically.