UNPKG

oneie

Version:

Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.

1,309 lines (1,165 loc) 40.9 kB
--- title: Elizaos dimension: connections category: elizaos.md tags: agent, ai, architecture, knowledge related_dimensions: events, knowledge scope: global created: 2025-11-03 updated: 2025-11-03 version: 1.0.0 ai_context: | This document is part of the connections dimension in the elizaos.md category. Location: one/connections/elizaos.md Purpose: Documents elizaos integration - multi-agent communication Related dimensions: events, knowledge For AI agents: Read this to understand elizaos. --- # ElizaOS Integration - Multi-Agent Communication **Version:** 1.0.0 **Purpose:** Enable ONE platform agents to communicate and collaborate with ElizaOS agents, creating a multi-agent ecosystem --- ## Overview ElizaOS is an open-source multi-agent AI development framework that allows building, deploying, and managing autonomous AI agents. This integration enables: 1. **ONE Agents ElizaOS Agents**: Our agents can message and collaborate with Eliza agents 2. **ElizaOS Agents ONE Agents**: Eliza agents can trigger actions in our system 3. **Shared Memory**: Agents can share context and knowledge across platforms 4. **Plugin Ecosystem**: Access ElizaOS's 90+ plugins for extended capabilities --- ## ElizaOS Architecture Overview ``` ┌─────────────────────────────────────────────────────────────────┐ ElizaOS Framework ├─────────────────────────────────────────────────────────────────┤ Core Components: ├─ Agent Runtime (@elizaos/server) ├─ Character System (personality files) ├─ Memory System (persistent conversation history) ├─ Plugin System (90+ plugins) └─ Multi-platform Adapters (Discord, Telegram, Twitter, etc.) └─────────────────────────────────────────────────────────────────┘ ┌──────────────────┐ REST API WebSocket/Socket.IO│ └──────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ ONE Platform Integration ├─────────────────────────────────────────────────────────────────┤ ElizaOSService (Effect.ts) ├─ Send messages to Eliza agents ├─ Receive messages from Eliza agents ├─ Share memory/context ├─ Trigger actions via plugins └─ Subscribe to agent events └─────────────────────────────────────────────────────────────────┘ ``` ### Key ElizaOS Concepts **1. Agents**: Autonomous AI entities with personality, memory, and goals **2. Character Files**: JSON definitions of agent personality and behavior **3. Actions**: What agents can do (send message, execute code, call API) **4. Providers**: Context aggregators (current time, user data, market data) **5. Evaluators**: Assess interactions and trigger behaviors **6. Plugins**: Modular capabilities (blockchain, social media, data analysis) --- ## Ontology Mapping ### Entity Types Used Uses the unified external integration schema from `Ontology.md`: ```typescript // EXTERNAL INTEGRATIONS (already in Ontology.md) | 'external_agent' // External AI agent (ElizaOS, AutoGen, CrewAI, etc.) | 'external_workflow' // External workflow (not used for ElizaOS) | 'external_connection' // Connection config to external service // EXISTING TYPES (reused) | 'conversation' // For agent-to-agent conversations | 'message' // For individual messages ``` ### Entity Properties **external_agent Properties (for ElizaOS agents):** ```typescript { platform: "elizaos", // Platform identifier agentId: string, // ElizaOS agent ID name: string, // Agent name description?: string, // What the agent does capabilities: string[], // Available actions/plugins apiEndpoint?: string, // REST API endpoint websocketUrl?: string, // WebSocket endpoint for real-time status: "online" | "offline" | "busy" | "unknown", lastSeen?: number, metadata: { // ElizaOS-specific data personality?: { traits: string[], goals: string[], bio: string, lore: string[], style: { all: string[], chat: string[], post: string[] } }, characterFile?: string, // Character definition URL/path platforms?: string[], // Discord, Telegram, Twitter, etc. tools?: string[], // Available ElizaOS tools model?: string // LLM model used }, conversationCount: number, // Total conversations messageCount: number, // Total messages exchanged createdAt: number, updatedAt: number } ``` **conversation Properties (for agent-to-agent chats):** ```typescript { participants: Id<'entities'>[], // Agent IDs in conversation type: "agent_to_agent" | "user_to_agent", platform: "elizaos", status: "active" | "ended" | "archived", messageCount: number, startedAt: number, endedAt?: number, lastMessageAt: number, metadata: { externalRoomId?: string, // Socket.IO room ID topic?: string, summary?: string, sentiment?: "positive" | "neutral" | "negative" } } ``` **message Properties (for conversation messages):** ```typescript { conversationId: Id<'entities'>, senderId: Id<'entities'>, // Entity ID (agent or user) senderType: "one_agent" | "external_agent" | "user", content: { text: string, action?: string, metadata?: any }, platform: "elizaos", embedding?: number[], // Vector embedding for RAG timestamp: number, deliveredAt?: number, readAt?: number } ``` **external_connection Properties (for ElizaOS connection):** ```typescript { platform: "elizaos", name: string, // Connection name baseUrl?: string, // ElizaOS server URL apiKey?: string, // Encrypted API key websocketUrl?: string, // WebSocket endpoint webhookSecret?: string, // Webhook signature secret connectionType: "rest" | "websocket" | "webhook", authentication: { type: "apiKey" | "bearer", credentials: any // Encrypted credentials }, status: "active" | "inactive" | "error", lastConnectedAt?: number, lastError?: string, linkedEntityIds: string[], // Connected ElizaOS agent IDs rateLimits?: { requestsPerMinute: number, requestsPerDay: number }, createdAt: number, updatedAt: number } ``` ### Connection Types Use existing connection types: ```typescript // ONE Agent ElizaOS Agent (collaboration) { fromEntityId: oneAgentId, toEntityId: externalAgentId, // external_agent entity relationshipType: 'collaborates_with', // Existing type metadata: { platform: 'elizaos', collaborationType: 'external_agent', permissions: ['message', 'read_memory', 'trigger_action'], establishedAt: Date.now() } } // User ElizaOS Agent (following) { fromEntityId: userId, toEntityId: externalAgentId, relationshipType: 'following', // Existing type metadata: { platform: 'elizaos', followedEntityType: 'external_agent', notificationsEnabled: true } } // Message Conversation { fromEntityId: messageId, toEntityId: conversationId, relationshipType: 'part_of', // Existing type metadata: { containerType: 'conversation', order: 42, platform: 'elizaos' } } ``` ### Event Types Use existing consolidated event types: ```typescript // Message sent to ElizaOS agent { type: 'agent_executed', // Existing type actorId: oneAgentId, targetId: externalAgentId, // external_agent entity timestamp: Date.now(), metadata: { action: 'message_sent', platform: 'elizaos', conversationId: conversationId, messageText: 'Hello ElizaOS agent!', transport: 'websocket' } } // Message received from ElizaOS agent { type: 'agent_executed', // Existing type actorId: externalAgentId, // external_agent entity targetId: oneAgentId, timestamp: Date.now(), metadata: { action: 'message_received', platform: 'elizaos', conversationId: conversationId, messageText: 'Hello ONE agent!', sentiment: 'positive' } } // Conversation started { type: 'content_changed', // Existing type actorId: userId, targetId: conversationId, timestamp: Date.now(), metadata: { action: 'created', contentType: 'conversation', platform: 'elizaos', participants: [oneAgentId, externalAgentId] } } // Agent collaboration failed { type: 'agent_failed', // Existing type actorId: oneAgentId, targetId: externalAgentId, timestamp: Date.now(), metadata: { action: 'collaboration_failed', platform: 'elizaos', error: 'Connection timeout', transport: 'websocket' } } ``` --- ## Effect.ts Service Implementation ### ElizaOSProvider ```typescript import { Effect, Layer, Schedule } from 'effect'; import { HttpProvider } from './http'; import { io, Socket } from 'socket.io-client'; export class ElizaOSError extends Error { readonly _tag = 'ElizaOSError'; constructor( public readonly message: string, public readonly agentId?: string, public readonly statusCode?: number ) { super(message); } } export class ElizaOSProvider extends Effect.Service<ElizaOSProvider>()( 'ElizaOSProvider', { effect: Effect.gen(function* () { const http = yield* HttpProvider; let socket: Socket | null = null; return { /** * Connect to ElizaOS WebSocket server */ connect: (args: { websocketUrl: string; apiKey?: string }) => Effect.gen(function* () { yield* Effect.sync(() => { socket = io(args.websocketUrl, { auth: args.apiKey ? { token: args.apiKey } : undefined, transports: ['websocket'], }); }); yield* Effect.async<void, ElizaOSError>((resume) => { if (!socket) { resume(Effect.fail(new ElizaOSError('Socket not initialized'))); return; } socket.on('connect', () => { resume(Effect.succeed(undefined)); }); socket.on('connect_error', (error) => { resume(Effect.fail(new ElizaOSError(`Connection failed: ${error.message}`))); }); }); }), /** * Disconnect from WebSocket server */ disconnect: () => Effect.sync(() => { if (socket) { socket.disconnect(); socket = null; } }), /** * Send message to Eliza agent via WebSocket */ sendMessage: (args: { agentId: string; userId: string; text: string; roomId?: string; }) => Effect.gen(function* () { if (!socket || !socket.connected) { yield* Effect.fail(new ElizaOSError('Not connected to ElizaOS')); } const messageData = { agentId: args.agentId, userId: args.userId, text: args.text, roomId: args.roomId, }; yield* Effect.async<any, ElizaOSError>((resume) => { if (!socket) { resume(Effect.fail(new ElizaOSError('Socket not initialized'))); return; } socket.emit('message', messageData, (response: any) => { if (response.error) { resume(Effect.fail(new ElizaOSError(response.error))); } else { resume(Effect.succeed(response)); } }); }); }), /** * Subscribe to messages from Eliza agent */ subscribeToMessages: (args: { agentId: string; roomId?: string; onMessage: (message: any) => void; }) => Effect.sync(() => { if (!socket) { throw new Error('Socket not initialized'); } if (args.roomId) { socket.emit('join', { roomId: args.roomId }); } socket.on('message', (message: any) => { if (message.agentId === args.agentId) { args.onMessage(message); } }); // Return cleanup function return () => { if (args.roomId && socket) { socket.emit('leave', { roomId: args.roomId }); } if (socket) { socket.off('message'); } }; }), /** * Get agent details via REST API */ getAgent: (args: { baseUrl: string; agentId: string; apiKey?: string }) => Effect.gen(function* () { const result = yield* http .get({ url: `${args.baseUrl}/api/agents/${args.agentId}`, headers: args.apiKey ? { Authorization: `Bearer ${args.apiKey}`, } : undefined, }) .pipe( Effect.catchAll((error) => Effect.fail( new ElizaOSError( `Failed to get agent: ${error.message}`, args.agentId, error.statusCode ) ) ) ); return result.data as { id: string; name: string; character?: any; status: string; platforms: string[]; }; }), /** * List available agents */ listAgents: (args: { baseUrl: string; apiKey?: string }) => Effect.gen(function* () { const result = yield* http .get({ url: `${args.baseUrl}/api/agents`, headers: args.apiKey ? { Authorization: `Bearer ${args.apiKey}`, } : undefined, }) .pipe( Effect.catchAll((error) => Effect.fail(new ElizaOSError(`Failed to list agents: ${error.message}`)) ) ); return result.data as Array<{ id: string; name: string; status: string; }>; }), /** * Get conversation history with Eliza agent */ getConversationHistory: (args: { baseUrl: string; agentId: string; userId: string; roomId?: string; apiKey?: string; }) => Effect.gen(function* () { const result = yield* http .get({ url: `${args.baseUrl}/api/agents/${args.agentId}/conversations`, params: { userId: args.userId, roomId: args.roomId, }, headers: args.apiKey ? { Authorization: `Bearer ${args.apiKey}`, } : undefined, }) .pipe( Effect.catchAll((error) => Effect.fail( new ElizaOSError(`Failed to get conversation: ${error.message}`) ) ) ); return result.data as { messages: Array<{ userId: string; text: string; timestamp: number; }>; }; }), /** * Trigger action on Eliza agent via plugin */ triggerAction: (args: { baseUrl: string; agentId: string; action: string; params: Record<string, any>; apiKey?: string; }) => Effect.gen(function* () { const result = yield* http .post({ url: `${args.baseUrl}/api/agents/${args.agentId}/actions`, body: { action: args.action, params: args.params, }, headers: { 'Content-Type': 'application/json', ...(args.apiKey ? { Authorization: `Bearer ${args.apiKey}`, } : {}), }, }) .pipe( Effect.catchAll((error) => Effect.fail( new ElizaOSError( `Failed to trigger action: ${error.message}`, args.agentId ) ) ) ); return result.data; }), }; }), dependencies: [HttpProvider.Default], } ) {} ``` ### ElizaOSService (Business Logic) ```typescript import { Effect } from 'effect'; import { ConvexDatabase } from './convex-database'; import { ElizaOSProvider } from './elizaos-provider'; export class ElizaOSService extends Effect.Service<ElizaOSService>()( 'ElizaOSService', { effect: Effect.gen(function* () { const db = yield* ConvexDatabase; const eliza = yield* ElizaOSProvider; return { /** * Send message from ONE agent to Eliza agent */ sendMessageToElizaAgent: (args: { oneAgentId: Id<'entities'>; elizaAgentId: Id<'entities'>; text: string; conversationId?: Id<'entities'>; }) => Effect.gen(function* () { // 1. Get Eliza agent entity const elizaAgent = yield* db.get(args.elizaAgentId).pipe( Effect.flatMap((agent) => agent?.type === 'eliza_agent' ? Effect.succeed(agent) : Effect.fail(new Error('Invalid Eliza agent')) ) ); // 2. Get connection config const connection = yield* db .query('entities') .filter((q) => q.eq(q.field('type'), 'eliza_connection')) .collect() .pipe(Effect.map((conns) => conns[0])); if (!connection) { yield* Effect.fail(new Error('No ElizaOS connection configured')); } // 3. Get or create conversation let conversationId = args.conversationId; if (!conversationId) { conversationId = yield* db.insert('entities', { type: 'eliza_conversation', name: `Conversation with ${elizaAgent.name}`, properties: { elizaAgentId: elizaAgent.properties.agentId, oneAgentId: args.oneAgentId, platform: 'websocket', status: 'active', messageCount: 0, startedAt: Date.now(), lastMessageAt: Date.now(), metadata: {}, }, status: 'active', createdAt: Date.now(), updatedAt: Date.now(), }); // Create connection yield* db.insert('connections', { fromEntityId: args.oneAgentId, toEntityId: args.elizaAgentId, relationshipType: 'collaborates_with', metadata: { collaborationType: 'eliza_agent', conversationId, }, createdAt: Date.now(), }); } // 4. Send message via ElizaOS const response = yield* eliza .sendMessage({ agentId: elizaAgent.properties.agentId, userId: args.oneAgentId, text: args.text, }) .pipe( Effect.retry({ times: 2, schedule: Schedule.exponential('1 second'), }) ); // 5. Store outgoing message const messageId = yield* db.insert('entities', { type: 'eliza_message', name: 'Message', properties: { conversationId, senderId: args.oneAgentId, senderType: 'one_agent', content: { text: args.text, }, timestamp: Date.now(), deliveredAt: Date.now(), }, status: 'active', createdAt: Date.now(), updatedAt: Date.now(), }); // 6. Create message connection yield* db.insert('connections', { fromEntityId: messageId, toEntityId: conversationId, relationshipType: 'part_of', metadata: { containerType: 'conversation', }, createdAt: Date.now(), }); // 7. Log event yield* db.insert('events', { type: 'agent_executed', actorId: args.oneAgentId, targetId: args.elizaAgentId, timestamp: Date.now(), metadata: { action: 'message_sent', conversationId, messageText: args.text, platform: 'websocket', }, }); // 8. Update conversation const conversation = yield* db.get(conversationId); yield* db.patch(conversationId, { properties: { ...conversation!.properties, messageCount: (conversation!.properties.messageCount || 0) + 1, lastMessageAt: Date.now(), }, }); return { conversationId, messageId, response, }; }), /** * Sync Eliza agents from ElizaOS instance */ syncElizaAgents: (args: { connectionId: Id<'entities'>; userId: Id<'entities'> }) => Effect.gen(function* () { // 1. Get connection const connection = yield* db.get(args.connectionId).pipe( Effect.flatMap((conn) => conn?.type === 'eliza_connection' ? Effect.succeed(conn) : Effect.fail(new Error('Invalid connection')) ) ); // 2. List agents from ElizaOS const agents = yield* eliza.listAgents({ baseUrl: connection.properties.baseUrl, apiKey: connection.properties.apiKey, }); // 3. Create/update agent entities const results = yield* Effect.all( agents.map((agent) => Effect.gen(function* () { // Get agent details const agentDetails = yield* eliza.getAgent({ baseUrl: connection.properties.baseUrl, agentId: agent.id, apiKey: connection.properties.apiKey, }); // Check if exists const existing = yield* db .query('entities') .filter((q) => q.and( q.eq(q.field('type'), 'eliza_agent'), q.eq(q.field('properties.agentId'), agent.id) ) ) .collect() .pipe(Effect.map((results) => results[0])); if (existing) { // Update yield* db.patch(existing._id, { properties: { ...existing.properties, name: agentDetails.name, status: agentDetails.status, platforms: agentDetails.platforms || [], updatedAt: Date.now(), }, }); return existing._id; } else { // Create const agentId = yield* db.insert('entities', { type: 'eliza_agent', name: agentDetails.name, properties: { agentId: agent.id, name: agentDetails.name, personality: agentDetails.character || {}, platforms: agentDetails.platforms || [], capabilities: [], status: agentDetails.status, conversationCount: 0, messageCount: 0, createdAt: Date.now(), updatedAt: Date.now(), }, status: 'active', createdAt: Date.now(), updatedAt: Date.now(), }); return agentId; } }) ), { concurrency: 5 } ); return { synced: results.length, agentIds: results, }; }), /** * Subscribe to messages from Eliza agent (WebSocket) */ subscribeToElizaAgent: (args: { connectionId: Id<'entities'>; elizaAgentId: Id<'entities'>; onMessage: (message: { conversationId: Id<'entities'>; messageId: Id<'entities'>; text: string; }) => void; }) => Effect.gen(function* () { // 1. Get connection const connection = yield* db.get(args.connectionId).pipe( Effect.flatMap((conn) => conn?.type === 'eliza_connection' ? Effect.succeed(conn) : Effect.fail(new Error('Invalid connection')) ) ); // 2. Get Eliza agent const elizaAgent = yield* db.get(args.elizaAgentId).pipe( Effect.flatMap((agent) => agent?.type === 'eliza_agent' ? Effect.succeed(agent) : Effect.fail(new Error('Invalid Eliza agent')) ) ); // 3. Connect to WebSocket if (connection.properties.websocketUrl) { yield* eliza.connect({ websocketUrl: connection.properties.websocketUrl, apiKey: connection.properties.apiKey, }); } // 4. Subscribe to messages const cleanup = yield* eliza.subscribeToMessages({ agentId: elizaAgent.properties.agentId, onMessage: async (message: any) => { // Store incoming message try { // Find conversation const conversations = await db .query('entities') .filter((q) => q.and( q.eq(q.field('type'), 'eliza_conversation'), q.eq(q.field('properties.elizaAgentId'), elizaAgent.properties.agentId), q.eq(q.field('properties.status'), 'active') ) ) .collect(); const conversation = conversations[0]; if (!conversation) return; // Store message const messageId = await db.insert('entities', { type: 'eliza_message', name: 'Message', properties: { conversationId: conversation._id, senderId: elizaAgent.properties.agentId, senderType: 'eliza_agent', content: { text: message.text, }, timestamp: Date.now(), }, status: 'active', createdAt: Date.now(), updatedAt: Date.now(), }); // Log event await db.insert('events', { type: 'agent_executed', actorId: args.elizaAgentId, targetId: conversation.properties.oneAgentId, timestamp: Date.now(), metadata: { action: 'message_received', conversationId: conversation._id, messageText: message.text, }, }); // Callback args.onMessage({ conversationId: conversation._id, messageId, text: message.text, }); } catch (error) { console.error('Failed to process Eliza message:', error); } }, }); return cleanup; }), }; }), dependencies: [ConvexDatabase.Default, ElizaOSProvider.Default], } ) {} ``` --- ## Convex Function Wrappers ```typescript // convex/elizaos.ts import { mutation, query } from './_generated/server'; import { v } from 'convex/values'; import { confect } from './confect'; import { ElizaOSService } from './services/elizaos'; import { MainLayer } from './layers'; /** * Send message to Eliza agent */ export const sendMessageToElizaAgent = confect.mutation({ args: { oneAgentId: v.id('entities'), elizaAgentId: v.id('entities'), text: v.string(), conversationId: v.optional(v.id('entities')), }, handler: (ctx, args) => Effect.gen(function* () { const service = yield* ElizaOSService; return yield* service.sendMessageToElizaAgent(args); }).pipe(Effect.provide(MainLayer)), }); /** * Sync Eliza agents from instance */ export const syncElizaAgents = confect.mutation({ args: { connectionId: v.id('entities'), }, handler: (ctx, args) => Effect.gen(function* () { const userId = yield* getUserId(ctx); const service = yield* ElizaOSService; return yield* service.syncElizaAgents({ connectionId: args.connectionId, userId, }); }).pipe(Effect.provide(MainLayer)), }); /** * Get conversation history */ export const getConversationHistory = query({ args: { conversationId: v.id('entities'), limit: v.optional(v.number()), }, handler: async (ctx, args) => { const conversation = await ctx.db.get(args.conversationId); if (!conversation || conversation.type !== 'eliza_conversation') { throw new Error('Invalid conversation'); } const messages = await ctx.db .query('entities') .filter((q) => q.and( q.eq(q.field('type'), 'eliza_message'), q.eq(q.field('properties.conversationId'), args.conversationId) ) ) .order('desc') .take(args.limit ?? 100); return { conversation, messages, }; }, }); /** * List Eliza agents */ export const listElizaAgents = query({ args: {}, handler: async (ctx) => { const agents = await ctx.db .query('entities') .filter((q) => q.eq(q.field('type'), 'eliza_agent')) .collect(); return agents; }, }); ``` --- ## Usage Examples ### 1. Strategy Agent Consulting with Eliza Marketing Expert ```typescript export class StrategyAgent extends Effect.Service<StrategyAgent>()( 'StrategyAgent', { effect: Effect.gen(function* () { const elizaService = yield* ElizaOSService; return { consultMarketingExpert: (args: { campaignIdea: string }) => Effect.gen(function* () { // Send question to Eliza marketing agent const result = yield* elizaService.sendMessageToElizaAgent({ oneAgentId: 'agent-strategy', elizaAgentId: 'eliza-marketing-expert', text: `I'm planning a campaign: "${args.campaignIdea}". What do you think about the market fit and messaging strategy?`, }); // Wait for response (handled via WebSocket subscription) return result; }), }; }), } ) {} ``` ### 2. Multi-Agent Brainstorming Session ```typescript export const startBrainstormingSession = confect.mutation({ args: { topic: v.string(), elizaAgentIds: v.array(v.id('entities')), }, handler: (ctx, args) => Effect.gen(function* () { const service = yield* ElizaOSService; const userId = yield* getUserId(ctx); // Send topic to all Eliza agents const responses = yield* Effect.all( args.elizaAgentIds.map((agentId) => service.sendMessageToElizaAgent({ oneAgentId: userId, elizaAgentId: agentId, text: `Brainstorming session on: "${args.topic}". Share your ideas and insights.`, }) ), { concurrency: 3 } ); return { conversationIds: responses.map((r) => r.conversationId), }; }).pipe(Effect.provide(MainLayer)), }); ``` ### 3. Real-time Message Subscription ```typescript // Long-running action that subscribes to Eliza agent export const subscribeToElizaMessages = confect.action({ args: { connectionId: v.id('entities'), elizaAgentId: v.id('entities'), }, handler: (ctx, args) => Effect.gen(function* () { const service = yield* ElizaOSService; const cleanup = yield* service.subscribeToElizaAgent({ connectionId: args.connectionId, elizaAgentId: args.elizaAgentId, onMessage: (message) => { console.log('Received message from Eliza:', message); // Process message, trigger workflows, notify users, etc. }, }); // Keep subscription alive yield* Effect.sleep('24 hours'); // Cleanup cleanup(); }).pipe(Effect.provide(MainLayer)), }); ``` --- ## Frontend Integration ### React Component for Eliza Chat ```tsx // src/components/elizaos/ElizaChat.tsx import { useMutation, useQuery } from 'convex/react'; import { api } from '@/convex/_generated/api'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { useState } from 'react'; export function ElizaChat({ oneAgentId, elizaAgentId, }: { oneAgentId: Id<'entities'>; elizaAgentId: Id<'entities'>; }) { const [message, setMessage] = useState(''); const [conversationId, setConversationId] = useState<Id<'entities'> | undefined>(); const sendMessage = useMutation(api.elizaos.sendMessageToElizaAgent); const conversation = useQuery( api.elizaos.getConversationHistory, conversationId ? { conversationId } : 'skip' ); const handleSend = async () => { const result = await sendMessage({ oneAgentId, elizaAgentId, text: message, conversationId, }); setConversationId(result.conversationId); setMessage(''); }; return ( <div className="flex flex-col h-full"> <div className="flex-1 overflow-y-auto p-4 space-y-2"> {conversation?.messages.map((msg) => ( <div key={msg._id} className={ msg.properties.senderType === 'one_agent' ? 'text-right' : 'text-left' } > <div className={`inline-block p-2 rounded ${ msg.properties.senderType === 'one_agent' ? 'bg-primary text-primary-foreground' : 'bg-muted' }`} > {msg.properties.content.text} </div> </div> ))} </div> <div className="p-4 border-t flex gap-2"> <Input value={message} onChange={(e) => setMessage(e.target.value)} placeholder="Message Eliza agent..." onKeyDown={(e) => e.key === 'Enter' && handleSend()} /> <Button onClick={handleSend}>Send</Button> </div> </div> ); } ``` --- ## Benefits ### For AI Agents 1. **Cross-Platform Collaboration**: ONE agents work with Eliza agents across platforms 2. **Specialized Expertise**: Access Eliza agents trained in specific domains 3. **Plugin Ecosystem**: Use ElizaOS's 90+ plugins for extended capabilities 4. **Multi-Agent Workflows**: Orchestrate complex tasks across agent platforms ### For Users 1. **Extended Capabilities**: Combine ONE platform features with ElizaOS plugins 2. **Choice of Agents**: Use best agent for each task (ONE or Eliza) 3. **Unified Interface**: Manage all agent interactions in ONE platform 4. **Community Agents**: Access community-built Eliza agents ### For Platform 1. **Ecosystem Integration**: Connect with ElizaOS developer community 2. **Reduced Development**: Leverage existing Eliza agents and plugins 3. **Interoperability**: Position as multi-agent platform hub 4. **Innovation**: Enable novel multi-agent use cases --- ## Security Considerations 1. **API Key Storage**: Encrypt ElizaOS API keys in database 2. **Message Validation**: Sanitize all messages before sending 3. **Rate Limiting**: Prevent message spam to Eliza agents 4. **Permission Checks**: Verify user has permission to contact agents 5. **WebSocket Security**: Validate WebSocket connections and messages 6. **Agent Verification**: Verify Eliza agent identity before trusting responses --- ## Testing ```typescript // tests/elizaos.test.ts import { Effect, Layer } from 'effect'; import { ElizaOSService } from '@/convex/services/elizaos'; describe('ElizaOSService', () => { it('should send message to Eliza agent', async () => { const MockEliza = Layer.succeed(ElizaOSProvider, { sendMessage: () => Effect.succeed({ messageId: 'msg-123', response: 'Hello from Eliza!', }), }); const result = await Effect.runPromise( Effect.gen(function* () { const service = yield* ElizaOSService; return yield* service.sendMessageToElizaAgent({ oneAgentId: 'agent-123', elizaAgentId: 'eliza-456', text: 'Hello Eliza!', }); }).pipe(Effect.provide(Layer.merge(MockEliza, MockDB))) ); expect(result.response).toBeDefined(); }); }); ``` --- ## Summary This integration enables: - **ONE Agents ElizaOS**: Agents collaborate with Eliza agents - **Real-time Communication**: WebSocket-based messaging - **Conversation Persistence**: Store all agent-to-agent conversations - **100% Effect.ts**: Typed errors, automatic retry, composable - **Non-Breaking**: Uses existing connection/event types - **Minimal Entities**: Only 4 new entity types needed **Next Steps**: 1. Add 4 entity types to Ontology.md 2. Implement ElizaOSProvider and ElizaOSService 3. Create Convex function wrappers 4. Build frontend chat UI for Eliza agents 5. Test with ElizaOS instance 6. Enable plugin integration