10 KiB
10 KiB
AI Process Builder + Chat Orchestrator
A complete implementation of tenant-scoped AI process automation where admins design LangGraph-compiled workflows via React Flow UI, and end-users execute them through a Deep Agent chat orchestrator with deterministic, audited execution.
Architecture Overview
Backend Components
1. Deep Agent Orchestrator (deep-agent.orchestrator.ts)
- Uses LangChain/OpenAI to intelligently select processes
- Extracts structured inputs from natural language
- Generates friendly confirmation messages
- Three-step workflow: discover → select → extract → execute
2. Graph Compiler (ai-processes.compiler.ts)
- Validates ReactFlow JSON graphs (Start/End nodes, reachability, cycles)
- Compiles to LangGraph-compatible state machines
- Validates tool allowlist and JSON schemas (Ajv)
- Persists compiled artifact for versioned execution
3. Runtime Executor (ai-processes.runner.ts)
- Executes compiled graphs deterministically
- Implements 4 node types: LLMDecisionNode, ToolNode, HumanInputNode, End
- Handles conditional edges via jsonlogic
- Emits real-time events for streaming updates
4. Tool Registry (tools/tool-registry.ts)
- Tenant-scoped tool allowlist (database-backed via AiToolConfig)
- Demo tools wrapping ObjectService (findAccount, createAccount, etc.)
- Context injection (tenantId, userId, knex) for secure execution
5. Orchestrator Service (ai-processes.orchestrator.service.ts)
- Integrates Deep Agent for process selection
- Falls back to standard AI assistant when no processes configured
- Manages chat sessions and message history
- Streams execution events via SSE
Frontend Components
1. AIChatBar (components/AIChatBar.vue)
- Updated to call
/ai-processes/chat/messagesendpoint - SSE event stream consumer for real-time updates
- Displays process selection, node execution, tool calls
- Handles NEED_INPUT events for human-in-the-loop
2. Process Management UI (pages/ai-processes/)
- List view: displays all processes with versions
- Editor view: React Flow integration via iframe + postMessage
- Test runner for quick validation
3. React Flow Editor (ai-processes-editor/src/App.tsx)
- Node palette: Start, LLMDecisionNode, ToolNode, HumanInputNode, End
- Visual graph designer with drag-drop
- Auto-saves to parent window via postMessage
- Loads existing graphs for editing
Data Models (Objection.js)
AiProcess
├── id, tenantId, name, description, latestVersion
└── relations: versions[], runs[]
AiProcessVersion
├── id, tenantId, processId, version
├── graphJson (ReactFlow definition)
└── compiledJson (LangGraph artifact)
AiProcessRun
├── id, tenantId, processId, version, status
├── inputJson, outputJson, errorJson, stateJson
└── currentNodeId (for resume)
AiChatSession
├── id, tenantId, userId
└── relations: messages[]
AiChatMessage
├── id, sessionId, role, content
└── timestamps
AiAuditEvent
├── id, tenantId, runId, eventType
└── payloadJson (full event data)
AiToolConfig
├── id, tenantId, toolName, enabled
└── configJson (tool-specific settings)
Demo Process: Register New Pet
A complete workflow demonstrating conditional logic and tool orchestration:
-
Extract Info (LLMDecisionNode)
- Parses user message for pet + owner details
- Outputs structured JSON with validation
-
Find/Create Account (Conditional)
- Searches for existing account by name/email
- Creates new account if not found
- Merges results into state
-
Find/Create Contact (Conditional)
- Searches for existing contact under account
- Creates new contact if not found
-
Create Pet (ToolNode)
- Inserts pet record linked to contact
- Returns pet ID
Seed the Demo Process
cd backend
npm run migrate:tenant -- <tenant-slug>
npm run seed:demo-process -- <tenant-slug>
Test the Demo Process
- Navigate to
/ai-processesin your tenant subdomain - Open "Register New Pet" process
- Click "Test Run" or use the chat bar:
User: "Register a dog named Max, breed Golden Retriever, age 3,
owned by John Smith, email john@example.com"
Agent: 🔄 Selected process: Register New Pet
I'll register Max (Golden Retriever, 3 years old) for John Smith.
⚙️ Executing step: Extract Info
✓ Extracted pet details
🔧 Using tool: findAccount
ℹ️ Account not found, creating new account
🔧 Using tool: createAccount
✓ Created account for John Smith
🔧 Using tool: findContact
ℹ️ Contact not found, creating new contact
🔧 Using tool: createContact
✓ Created contact: John Smith
🔧 Using tool: createPet
✓ Created pet: Max (ID: pet_1234567890)
✅ Process completed successfully!
API Endpoints
Process Management (Admin)
GET /tenants/:tenantId/ai-processes
POST /tenants/:tenantId/ai-processes
GET /tenants/:tenantId/ai-processes/:id
POST /tenants/:tenantId/ai-processes/:id/versions
GET /tenants/:tenantId/ai-processes/:id/versions
POST /tenants/:tenantId/ai-processes/:id/runs
POST /tenants/:tenantId/ai-processes/runs/:runId/resume
Chat Orchestrator (End User)
POST /tenants/:tenantId/ai-processes/chat/messages
SSE /tenants/:tenantId/ai-processes/stream?sessionId=xxx
Event Stream Types
type StreamEvent =
| { type: 'agent_started' }
| { type: 'processes_listed', data: { count: number } }
| { type: 'process_selected', processId: string, version: number }
| { type: 'agent_message', data: { message: string } }
| { type: 'node_started', nodeId: string }
| { type: 'node_completed', nodeId: string }
| { type: 'tool_called', toolName: string, nodeId: string }
| { type: 'llm_decision', nodeId: string, data: any }
| { type: 'need_input', data: { prompt: string, schema: JSONSchema } }
| { type: 'final', data: { output: any } }
| { type: 'error', data: { error: string } }
Security & Guardrails
1. Tenancy Isolation
- All queries filtered by
tenantId(enforced in Objection models) - Tool context includes tenant scope
- Database-per-tenant architecture (inherited from platform)
2. Tool Allowlist
- Two-level validation:
- Tenant-level:
AiToolConfigtable (enabled tools per tenant) - Compile-time: validates toolName exists in registry
- Tenant-level:
- Runtime check before tool execution
3. Schema Validation
- LLMDecisionNode output validated against JSON Schema (Ajv)
- HumanInputNode input validated before resume
- Graph structure validated at compile time
4. Audit Trail
- Every node execution logged to
ai_audit_events - Includes: tool calls, LLM decisions, state mutations, errors
- Queryable for compliance dashboards
5. Versioning
- Immutable process versions (create-only)
- Runs reference specific version number
- Graph definition + compiled artifact stored together
Running the System
1. Run Migrations
cd backend
npm run migrate:tenant -- tenant1
2. Seed Demo Data
npm run seed:demo-process -- tenant1
3. Start Backend
npm run start:dev
4. Build Editor (if needed)
cd frontend/ai-processes-editor
npm install
npm run build
5. Start Frontend
cd frontend
npm run dev
6. Access UI
- Admin UI:
http://tenant1.localhost:3001/ai-processes - Chat UI: Available in bottom drawer on any page (⌘K to toggle)
Extension Points
Adding New Node Types
- Define type in ai-processes.types.ts
- Add schema validation in ai-processes.schemas.ts
- Implement executor in ai-processes.runner.ts
- Add UI component in React Flow editor
Adding New Tools
- Implement handler in tools/demo-tools.ts
- Register in
demoToolsexport - Add to tenant allowlist via UI or seed script
- Document input/output schema
Custom LLM Decision Logic
Override llmDecision callback in ai-processes.service.ts:
llmDecision: async (node, state) => {
const prompt = renderTemplate(node.data.promptTemplate, state);
const response = await callOpenAI(prompt, node.data.model);
return validateAgainstSchema(response, node.data.outputSchema);
}
Troubleshooting
Process not appearing in chat
- Check:
npm run seed:demo-processcompleted successfully - Verify: Process exists in database (
select * from ai_processes) - Check: Tools enabled (
select * from ai_tool_configs)
Graph validation errors
- Ensure exactly one Start node
- Ensure at least one End node
- Check all edges reference valid node IDs
- Verify tool names match registered tools
SSE stream not working
- Check CORS settings for subdomain routing
- Verify
sessionIdreturned from initial message - Check browser console for connection errors
- Fallback: use polling endpoint (TODO: implement)
Next Steps
- Enhanced Input Extraction: Use Deep Agent to extract required fields per process
- Visual Schema Builder: UI for JSON Schema creation (drag-drop fields)
- Conditional Edge Builder: Visual jsonlogic editor
- Process Analytics: Dashboard showing run success rates, avg duration
- Human-in-Loop UI: Dynamic form renderer for HumanInputNode
- Process Marketplace: Share processes across tenants (with permissions)
- Python Microservice: Optional Python runtime for native LangGraph support
License
MIT