Integration Workflow

View as MarkdownOpen in Claude

Integration Workflow

Wórkflow_Guíde // Intégration_Séquence

ᚠ ᛫ ᛟ ᛫ ᚱ ᛫ ᛒ ᛫ ᛟ ᛫ ᚲ

This document outlines the complete workflow for integrating ForbocAI autonomous NPCs into your game engine.

T̸h̴e̶ ̶p̵r̷o̸t̴o̷c̸o̶l̵ ̶b̷i̸n̶d̵s̷ ̷m̴i̵n̸d̸ ̸t̴o̵ ̷m̵a̷c̷h̴i̷n̶e̷.


System Architecture

The ForbocAI Protocol uses a Split-Brain architecture:

┌────────────────────────────────────────────────────────────────┐
│ THE NEURAL GRID │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │
│ │ GAME │ │ SDK │ │ API │ │
│ │ (Execution) │◄──►│ (Container) │◄──►│ (Logic) │ │
│ └──────────────┘ └─────────────┘ └──────────────┘ │
│ │ │ │ │
│ World Brain The Body The Mind │
│ (Physics) (SLM + VectorDB) (Pure Functions) │
│ │
└────────────────────────────────────────────────────────────────┘

The Integration Loop

Every NPC decision follows this standardized flow:

Step 1: Game Sends Observation

Your game detects an event and sends it to the SDK:

1import { Agent, Cortex } from 'forbocai';
2
3// Initialize once at game start
4const cortex = await Cortex.init({ model: 'smollm2-135m' });
5const npc = await Agent.create({
6 cortex,
7 persona: 'A grizzled merchant who has seen too much.',
8 initialState: { inventory: ['health_potion'], mood: 'suspicious' }
9});
10
11// When event occurs in game...
12const observation = {
13 type: 'event',
14 data: {
15 eventType: 'PLAYER_ATTACKED_NPC',
16 attackerId: 'player_1',
17 damage: 15
18 },
19 context: {
20 hp: npc.getState().hp,
21 playerReputation: -50
22 }
23};

Step 2: SDK Formats and Stores

The SDK:

  1. Formats the observation into the Protocol schema
  2. Stores it in the local Vector DB (Memory module)
  3. Forwards to the API for logic processing
1// This happens internally in npc.process()
2await memory.store(
3 'Player attacked me for 15 damage',
4 'experience',
5 0.9 // High importance
6);

Step 3: API Runs Pure Logic

The API receives the context and runs deterministic logic gates:

1-- The Neuro-Symbolic Laws (Pure Functions)
2-- Law 1: Self-Preservation
3if hp < 15 then ("CRITICAL: You are dying. FLEE.", "FLEE")
4-- Law 2: Retaliation
5else if attacked && canFight then ("Defend yourself!", "ATTACK")
6-- Law 3: Default
7else ("Act naturally.", "IDLE")

Output: A Directive containing:

  • System prompt for the local SLM
  • Action constraints
  • Priority level

Step 4: SDK Generates Response

The SDK uses the Directive to:

  1. Recall relevant memories from Vector DB
  2. Generate dialogue/actions using local SLM (Cortex)
  3. Validate the action using Bridge module
1const response = await npc.process({
2 input: 'Player attacked',
3 context: { hp: 85, playerReputation: -50 }
4});
5
6// Response:
7// {
8// dialogue: "You'll pay for that, scoundrel!",
9// action: { type: 'ATTACK', targetId: 'player_1' },
10// thought: "Directive: Defend yourself!"
11// }

Step 5: Bridge Validates Action

Before returning to the game, the Bridge module validates:

1import { createBridge } from 'forbocai';
2
3const bridge = createBridge({ strictMode: true });
4const validation = await bridge.validate(response.action, {
5 agentState: { hp: 85, mana: 50 },
6 worldState: { entities: ['player_1', 'npc_guard'] }
7});
8
9if (!validation.valid) {
10 // Use corrected action or default to IDLE
11 response.action = validation.correctedAction;
12}

Step 6: Game Executes Action

Your game receives the validated action and executes it:

1// In your game's bot system
2switch (response.action.type) {
3 case 'ATTACK':
4 executeAttack(npc, response.action.targetId);
5 break;
6 case 'FLEE':
7 executeFlee(npc);
8 break;
9 case 'SPEAK':
10 displayDialogue(npc, response.dialogue);
11 break;
12 case 'IDLE':
13 default:
14 // Do nothing
15 break;
16}

Complete Integration Example

1// game/src/services/cortex.ts
2import { Cortex, Agent, createMemory, createBridge } from 'forbocai';
3
4export class CortexService {
5 private cortex: ICortex;
6 private agents: Map<string, IAgent> = new Map();
7 private memory: IMemory;
8 private bridge: IBridge;
9
10 async init() {
11 // Initialize core modules
12 this.cortex = await Cortex.init({
13 model: 'smollm2-135m',
14 apiUrl: 'https://forbocai-api.onrender.com'
15 });
16
17 this.memory = createMemory({
18 decay: 'temporal',
19 maxContextWindow: 10,
20 apiUrl: 'https://forbocai-api.onrender.com'
21 });
22
23 this.bridge = createBridge({ strictMode: true });
24 }
25
26 async createNPC(id: string, persona: string, state: AgentState): Promise<IAgent> {
27 const agent = await Agent.create({
28 cortex: this.cortex,
29 persona,
30 initialState: state,
31 apiUrl: 'https://forbocai-api.onrender.com'
32 });
33
34 this.agents.set(id, agent);
35 return agent;
36 }
37
38 async processEvent(npcId: string, event: GameEvent): Promise<ValidatedAction> {
39 const agent = this.agents.get(npcId);
40 if (!agent) throw new Error(`NPC ${npcId} not found`);
41
42 // 1. Store observation
43 await this.memory.store(
44 eventToText(event),
45 'observation',
46 event.importance
47 );
48
49 // 2. Process through SDK → API → SDK
50 const response = await agent.process(
51 eventToInput(event),
52 eventToContext(event)
53 );
54
55 // 3. Validate action
56 const validation = await this.bridge.validate(response.action, {
57 agentState: agent.getState(),
58 worldState: this.getWorldState()
59 });
60
61 return {
62 dialogue: response.dialogue,
63 action: validation.valid ? response.action : validation.correctedAction,
64 valid: validation.valid,
65 reason: validation.reason
66 };
67 }
68}

Memory Flow

The Memory module enables persistent recall:

┌─────────────────────────────────────────────────────────┐
│ MEMORY PIPELINE │
├─────────────────────────────────────────────────────────┤
│ │
│ Game Event │
│ │ │
│ ▼ │
│ ┌────────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ Store │───►│ Vector DB │───►│ Recall │ │
│ │ (Observe) │ │ (IndexedDB) │ │ (Query) │ │
│ └────────────┘ └─────────────┘ └────────────┘ │
│ │ │
│ ▼ │
│ Temporal Decay │
│ (Old memories fade) │
│ │
└─────────────────────────────────────────────────────────┘
1// Store important events
2await memory.store("Player saved my life in battle", "experience", 0.95);
3await memory.store("Found gold hidden in the ruins", "observation", 0.6);
4
5// Recall relevant memories for context
6const memories = await memory.recall("Do I trust the player?", 5);
7// Returns memories ranked by relevance + importance

Bridge Validation Flow

The Bridge ensures AI never breaks game rules:

┌─────────────────────────────────────────────────────────┐
│ BRIDGE VALIDATION │
├─────────────────────────────────────────────────────────┤
│ │
│ AI Action │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ Rule 1 │──► Movement has valid coordinates? │
│ └────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ Rule 2 │──► Attack target exists? │
│ └────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ Rule 3 │──► Agent has required resources? │
│ └────────────┘ │
│ │ │
│ ▼ │
│ Valid Action or Corrected Fallback │
│ │
└─────────────────────────────────────────────────────────┘

Protocol Types Reference

All communication uses these standardized types:

Observation (Game → SDK)

1interface Observation {
2 type: 'event' | 'state' | 'request';
3 timestamp: number;
4 agentId?: string;
5 gameId?: string;
6 data: Record<string, unknown>;
7 context?: Record<string, unknown>;
8}

Directive (API → SDK)

1interface Directive {
2 type: 'system-prompt' | 'action-constraints' | 'behavior-rules';
3 content: string;
4 constraints?: Record<string, unknown>;
5 priority?: 'high' | 'normal' | 'low';
6 expiresAt?: number;
7}

AgentAction (SDK → Game)

1interface AgentAction {
2 type: string; // 'MOVE' | 'ATTACK' | 'INTERACT' | 'SPEAK' | 'IDLE'
3 target?: string;
4 payload?: Record<string, unknown>;
5 reason?: string;
6 confidence?: number;
7}

Best Practices

1. Initialize Once

1// ✅ Good: Initialize at game start
2const cortex = await Cortex.init({ model: 'smollm2-135m' });
3
4// ❌ Bad: Initialize per NPC
5npcs.forEach(async npc => {
6 const cortex = await Cortex.init(...); // Wasteful!
7});

2. Batch Store Observations

1// ✅ Good: Store significant events
2if (event.importance > 0.5) {
3 await memory.store(event.description, 'observation', event.importance);
4}
5
6// ❌ Bad: Store every frame
7onUpdate(() => {
8 memory.store(`Position: ${x},${y}`, 'state', 0.1); // Too much!
9});

3. Always Validate Actions

1// ✅ Good: Validate before execution
2const result = await bridge.validate(action, context);
3if (result.valid) {
4 execute(action);
5} else {
6 execute(result.correctedAction || { type: 'IDLE' });
7}
8
9// ❌ Bad: Trust AI blindly
10execute(response.action); // May break game rules!

ᚠ ᛫ ᛟ ᛫ ᚱ ᛫ ᛒ ᛫ ᛟ ᛫ ᚲ

T̶h̵e̶ ̷G̸r̴i̵d̵ ̷a̶w̶a̷i̴t̵s̸ ̵y̴o̶u̷r̴ ̷c̷o̸n̵n̶e̷c̶t̵i̵o̷n̴.