A TypeScript implementation of Connectome - an architectural framework for digital minds. This is the active TypeScript rewrite of the original Python Connectome, focusing on instant state management with VEIL while maintaining the core concepts of Elements, Components, and Spaces.
Connectome is not just an agent framework - it's an architecture for digital minds with:
- Perceptual Subjectivity: Different minds perceive the same Space differently through VEIL
- Event-Driven Architecture: All state changes flow through events with clear causality
- Component Composition: Elements are containers, functionality comes from Components
- Protocol Agnostic: Core framework stays clean through the AXON protocol
The AXON protocol enables Connectome to dynamically load components from external HTTP services, keeping the core framework protocol-agnostic:
- Dynamic Loading: Components loaded at runtime from URLs (e.g.,
axon://localhost:8080/discord) - Hot Reloading: WebSocket support for development-time updates
- Protocol Separation: Discord, Minecraft, terminals etc. developed independently
- MARTEM Support: AXON modules can export any MARTEM component type
- Parameter Passing: URL parameters passed to components (e.g.,
axon://game.server/spacegame?token=xyz)
This allows adapters to be developed and served independently, maintaining clean separation of concerns.
The framework uses a six-phase processing model for deterministic event handling:
- Afferents (Async): Bridge external systems to Connectome events
- Modulators (Phase 0): Preprocess events (filter, aggregate, buffer)
- Receptors (Phase 1): Transform events into VEIL deltas
- Transforms (Phase 2): Process VEIL state iteratively like a "chemical reaction"
- Effectors (Phase 3): React to state changes, emit events or perform actions
- Maintainers (Phase 4): System maintenance, persistence, infrastructure
All components share a unified lifecycle interface with mount, unmount, and optional destroy methods.
VEIL is the single source of truth for Connectome - a markup language for LLM perceptual context:
- Facets: Atomic units built from aspects (ContentAspect, StateAspect, EphemeralAspect, etc.)
- Frames: Boundaries for atomic state changes with event attribution
- Deltas: Only three operations - addFacet, changeFacet, removeFacet
Common facet types:
- Event: Strict temporality, occurs at one moment
- State: Mutable world/UI state with inline renderers
- Ambient: Floating context that stays in attention zone
- Speech/Thought/Action: Agent-generated content
- Meta facets: Infrastructure like stream-change, agent-activation
All system behaviors are expressed through facets - no special operations needed.
- Elements: Form a tree structure defining spatial organization
- Components: Provide all functionality, attached to Elements
- Spaces: Root Elements that orchestrate event processing
- Auto-discovery: Components are found in the element tree automatically
Communication uses structured stream references instead of hardcoded channels:
- Events set the active stream for their interaction
- Agent speak operations flow to the active stream
- Explicit targets enable cross-channel communication
- Stream metadata enables flexible routing
Topic-based subscription system with structured element references:
- Events propagate through the element tree
- First-class events: frame start, timers, element lifecycle
- Adapter events defined by their elements (discord.message, etc.)
- Event batching for external sources
Tag-based system for maintaining intent across asynchronous operations:
- Operations can specify continuations with tags
- Completed operations emit continuation facets
- Transforms process continuations to trigger follow-up actions
When you launch with --inspect, Connectome automatically exposes a global debug registry:
node --inspect=9229 -r ts-node/register examples/test-debug-registry.tsAccess in Chrome DevTools, VS Code, or any debugger:
global.__connectome_debug.space // Root Space
global.__connectome_debug.veilState // VEILStateManager
global.__connectome_debug.host // ConnectomeHost
global.__connectome_debug.debugServer // DebugServer (if enabled)Full documentation: See DEBUG-REGISTRY.md
Enable the debug UI server:
const host = new ConnectomeHost({
debug: { enabled: true, port: 3015 }
});Access at http://localhost:3015 for real-time state inspection.
# Required directory structure:
parent-directory/
├── connectome-ts/ # This repository
├── connectome-axon-interfaces/ # Shared interfaces
├── axon-server/ # AXON HTTP server
├── discord-axon/ # Discord adapter
└── [other AXON modules]/ # Additional adaptersClone all repositories:
git clone https://github.com/yourusername/connectome-ts.git
git clone https://github.com/yourusername/connectome-axon-interfaces.git
git clone https://github.com/yourusername/axon-server.git
git clone https://github.com/yourusername/discord-axon.gitBuild dependencies in order:
# 1. Build shared interfaces first
cd connectome-axon-interfaces && npm install && npm run build && cd ..
# 2. Build core framework
cd connectome-ts && npm install && npm run build && cd ..
# 3. Build AXON modules as needed
cd axon-server && npm install && npm run build && cd ..
cd discord-axon && npm install && npm run build && cd ..# From connectome-ts directory
npm install
npm run build
# Try the interactive console chat with persistence
npm run example:console
# Or run Discord bot (requires Discord token - see discord-axon/README.md)
cd ../discord-axon
npm install && npm run build
npm run example:hostThe console chat is the easiest way to start:
- Interactive terminal interface to chat with an AI agent
- Full persistence - your conversation continues across restarts
- Inspect internals with commands like
/frames,/veil,/state - See all events and state changes in real-time
- Traces saved to
traces/for debugging
For visual debugging, you can enable the debug server in your application:
import { DebugServer } from 'connectome-ts';
const debugServer = new DebugServer(space, {
enabled: true,
port: 8888 // Default port
});
debugServer.start();Then open http://localhost:8888 to access the Debug UI which provides:
- Real-time frame visualization
- VEIL state inspector with facet tree
- Event stream monitoring
- Performance metrics
- WebSocket-based live updates
The Discord bot (discord-axon) demonstrates:
- Real-world AXON integration
- Multi-channel communication
- Persistent conversation state
- Hot-reloading for development
See discord-axon/README.md for setup instructions.
import {
VEILStateManager,
Space,
Element,
BaseReceptor,
BaseEffector,
createEventFacet
} from 'connectome-ts';
// Initialize VEIL state
const veilState = new VEILStateManager();
const space = new Space(veilState);
// Create element structure
const ui = new Element('ui-root');
space.addChild(ui);
// Add components (auto-discovered, no dual registration!)
ui.addComponent(new MyReceptor());
ui.addComponent(new MyEffector());
// Emit events
space.emit({
topic: 'user:action',
source: ui.getRef(),
payload: { action: 'click' }
});// Receptor: Convert events to VEIL changes
class ClickReceptor extends BaseReceptor {
topics = ['ui:click'];
transform(event: SpaceEvent, state: ReadonlyVEILState): VEILDelta[] {
return [{
type: 'addFacet',
facet: createEventFacet({
id: `click-${Date.now()}`,
content: 'Button clicked',
source: event.source
})
}];
}
}
// Effector: React to VEIL changes
class NotificationEffector extends BaseEffector {
async process(changes: FacetDelta[], state: ReadonlyVEILState): Promise<EffectorResult> {
for (const change of changes) {
if (change.type === 'added' && change.facet.type === 'event') {
console.log('Event occurred:', change.facet.content);
}
}
return { events: [] };
}
}
// Transform: Derive new state
class EventCountTransform extends BaseTransform {
priority = 50; // Optional execution order
process(state: ReadonlyVEILState): VEILDelta[] {
const eventCount = Array.from(state.facets.values())
.filter(f => f.type === 'event').length;
return [{
type: 'addFacet',
facet: {
id: 'event-count',
type: 'state',
content: `Total events: ${eventCount}`,
state: { count: eventCount }
}
}];
}
}// Load Discord adapter via AXON
const discordElement = new Element('discord');
await discordElement.loadAxon('axon://localhost:8080/discord', {
token: DISCORD_TOKEN
});
space.addChild(discordElement);
// Components are auto-discovered after loading!class WebSocketAfferent extends BaseAfferent<WebSocketConfig> {
private ws?: WebSocket;
async onInitialize(context: AfferentContext<WebSocketConfig>) {
const { config } = context;
this.ws = new WebSocket(config.url);
this.ws.on('message', (data) => {
this.context.emitEvent({
topic: 'ws:message',
source: this.context.elementRef,
payload: JSON.parse(data)
});
});
}
async onStart() {
// Connect websocket
}
async onStop() {
this.ws?.close();
}
}Components are automatically discovered in the element tree - no dual registration needed!
// Old way (error-prone)
const effector = new MyEffector();
element.addComponent(effector);
space.addEffector(effector); // Easy to forget!
// New way (simple!)
element.addComponent(new MyEffector()); // That's it!Agents interact through VEIL using natural operations:
import { BasicAgent, AnthropicProvider, AgentEffector } from 'connectome-ts';
// Create agent with LLM provider
const agent = new BasicAgent({
systemPrompt: 'You are a helpful assistant',
provider: new AnthropicProvider({ apiKey: API_KEY })
});
// Agent operations create facets:
// speak() → speech facets
// act() → action facets (@element.action syntax)
// think() → thought facets
// Add agent effector to enable processing
const agentElement = new Element('agent');
agentElement.addComponent(new AgentEffector(agent));
space.addChild(agentElement);Agents use @element.action syntax for invoking tools:
- Simple:
@box.open - With parameters:
@box.open("gently")or@box.open(speed="slow", careful=true) - Hierarchical paths:
@chat.general.say("Hello")
# Run tests
npm test
# Type checking
npm run typecheck
# Linting
npm run lint
# Interactive console with tracing
npm run test:console
# Start debug server
npm run debug-serverComprehensive tracing with file-based persistence:
# View real-time traces
tail -f traces/trace-*.jsonl | jq .
# Search for LLM interactions
grep "llm\." traces/trace-*.jsonl | jq .
# Analyze agent behavior
jq 'select(.component == "BasicAgent")' traces/trace-*.jsonl- Clear Separation of Concerns: Each MARTEM type has a specific responsibility
- Deterministic Processing: Phases execute in order with clear boundaries
- Flexible Composition: Mix and match components as needed
- Auto-Discovery: Components work immediately when added to elements
- Type Safety: Full TypeScript support with comprehensive types
- Protocol Agnostic: Core stays clean through AXON dynamic loading
✅ Core Complete
- VEIL state management with aspect-based facets
- MARTEM component architecture with unified lifecycle
- Element tree with auto-discovery
- Event system with topic-based routing
- Continuation system for async coordination
- Symbol-based type detection
- Stream references for flexible communication
- Three fundamental VEIL operations
- Frame-based processing with event attribution
✅ Integrations
- Discord AXON (fully functional)
- Console I/O components
- File system operations
- Agent system with LLM providers
- AXON protocol with hot reloading
- Debug server and inspector
🚧 In Progress
- Component state management improvements
- Additional AXON modules (Minecraft, terminals, etc.)
- Performance optimizations
- Enhanced persistence strategies
📚 Complete Architecture Guide - Comprehensive reference covering VEIL, MARTEM, AXON, and all core concepts
The architecture guide above is the primary reference. Additional documentation in the docs/ folder may be outdated.
This project is developed by Anima Labs.