-
-
Notifications
You must be signed in to change notification settings - Fork 17
Agent Loop
The agent loop is the core of CortexPrism. It processes one complete user→agent exchange through pipeline hooks, memory injection, MQM model selection, LLM calls, security-gated tool execution, and post-turn storage.
agentTurn(opts)
1. pipeline hooks (pre-assess stage)
2. injectMemory(systemPrompt, hits) ← prepend relevant memory with category, tags, entities
3. MQM model selection (pre-llm hook) ← enforce/suggest/defer based on confidence
4. persistMessage(userMessage)
5. [TOOL LOOP — up to MAX_TOOL_ROUNDS=8]
a. LLM call (buffered stream when tools registered)
b. parseToolCalls(response) ← extract <tool_call> XML + bare JSON fallback
c. for each call:
- validateToolCall() ← Parallax policy regex check
- [if sensitive data] → LLM supervisor review → human approval gate
- tool.execute()
- logEvent(tool_call)
d. formatToolResults() → re-prompt with escalating deadline instruction
6. persistMessage(agentResponse, stripped of tool calls)
7. incrementTurn(sessionId)
8. pipeline hooks (post-output stage)
9. writeEpisodic(summary) ← fire-and-forget
10. reflectOnTurn() [if enabled] ← fire-and-forget
11. extractSkillFromSession() ← fire-and-forget (≥2 tool calls)
return AgentTurnResult
| Option | Type | Purpose |
|---|---|---|
userMessage |
string | User input |
userContentBlocks |
ContentBlock[] | Multimodal content (images, documents) |
provider |
LLMProvider | Active LLM provider |
model |
string | Model name |
sessionDb |
Db | Per-session SQLite instance |
sessionId |
string | Session identifier |
systemPrompt |
string | System prompt (with injected memory + skills) |
stream |
boolean | Stream output chunks |
onChunk |
function | Chunk callback for streaming |
registry |
ToolRegistry | Registered tools |
toolContext |
ToolContext | Working dir, approval gate, policy state |
embedder |
EmbeddingProvider | For memory retrieval |
enableReflection |
boolean | Post-turn reflection |
reasoningEffort |
string | Extended thinking budget (low/medium/high) |
signal |
AbortSignal | Request timeout (90s default for tool rounds) |
After each tool execution round, the agent receives tool results and is re-prompted:
- Tool results are formatted as
<tool_result>XML blocks with structured error info - Results are appended as a user message in the conversation
- The LLM is called again with updated message history
- Up to 8 rounds (MAX_TOOL_ROUNDS) before hitting the ceiling
- When ≤1 rounds remain, a hard instruction stops tool calling and demands a final response
- Follow-up instructions escalate per round to prevent infinite tool loops
All tool rounds use buffered stream() with a 90-second AbortSignal timeout to prevent hanging on slow providers.
When tools access sensitive data (memory_search, db_query, browser, computer):
- Results are classified for sensitivity (SECRET/SENSITIVE/NORMAL/PUBLIC)
- SENSITIVE/SECRET results trigger the LLM supervisor review
- Supervisor evaluates agent intent, data sensitivity, and operational context
- High-confidence decisions auto-approve; low-confidence escalate to human
- Human approval (CLI prompt or Web UI modal with 60s timeout)
- Approved decisions cached per session (1-hour TTL) to prevent approval fatigue
When tools are registered, the LLM response is streamed into a buffer internally (not directly to the client). After the full response is received:
- Tool calls are extracted via brace-depth walker (handles nested JSON correctly)
- XML regions stripped before bare JSON fallback scan to prevent double-execution
- Only clean prose (no
<tool_call>XML, no<tool_result>XML, no bare JSON) is forwarded viaonChunk - Reasoning content extracted separately and sent as optional
reasoningmessage type - Client-side WebSocket handler double-checks stripping as a defensive safety net
These tasks run asynchronously after the response is sent — they never block the agent:
| Operation | Destination | Purpose |
|---|---|---|
writeEpisodic() |
episodic_memory |
Store turn summary |
extractAndStoreEntities() |
semantic_memory + graph_entities
|
Build knowledge graph (filtered by ENTITY_STOP_WORDS) |
detectAndPersistPreference() |
semantic_memory + MEMORY.md
|
Capture user preferences |
reflectOnTurn() → storeReflection()
|
reflection_memory |
Extract behavioral patterns (dedup by pattern text) |
logEvent() |
lens.db |
Audit log entry (35+ event types) |
extractSkillFromSession() |
procedural_memory |
Procedural knowledge (≥2 tool calls, params redacted) |
src/agent/metacog.ts analyzes user messages before the LLM call to determine delegation strategy:
-
Complex code + exploration →
delegatewith suggested types[explore, code] -
Research + independent subtasks →
parallelizewith[research] -
Pure exploration →
delegatewithexplore -
Destructive multi-step →
plan_with_rollbackwithplan
The suggestedSubAgents field guides the LLM in choosing sub-agent types. Meta-cog signals include isExploratory, isCodeTask, isPlanningTask, and isComplex.
10 hook stages run around the agent loop at:
-
pre-assess,post-assess— metacognition -
pre-reason,post-reason— context injection, summarization, model selection -
pre-tool,post-tool— tool orchestration (QM), output capture, loop detection -
pre-reflect,post-reflect— reflection -
pre-output,post-output— content safety, auto-TTS, audit, cost tracking
[loop] prefixed console.log statements track every tool round: turn ID, tool presence, stream mode, response length/preview, detected tool call names, per-tool execution results, prose emission length, and final response emission path.
- Sub-Agents — Child agent spawning and lifecycle
- Security — Policy validation and LLM supervisor
- Request Flow — Full request lifecycle diagrams
- Pipeline Hooks — Hook system reference
- Model Quartermaster — MQM model selection in agent context
Before each turn, assessTask() from src/agent/metacog.ts classifies the user's message:
| Signal | Trigger | Decision |
|---|---|---|
| Ambiguous intent | Ends with ? or vague language |
ask_first |
| Destructive | Contains "rm", "delete", "drop", "purge" | ask_first |
| Complex task | >20 words or multi-step instructions | plan_with_rollback |
| Independent subtasks | "and also", "then after", "first...second" | parallelize |
| Code task | Mentions "code", "function", "bug", "fix" | plan_with_rollback |
| General | None of the above | direct |
When the confidence score falls below 0.35 for a direct decision, the system auto-escalates to ask_first:
if confidence < 0.35 and decision === 'direct':
escalate to ask_first with a clarification prompt
log escalation event to lens_events
Every metacognition assessment is logged as a plan artifact via src/agent/planner.ts:
- Plan artifacts include decision, confidence, signal breakdown, and suggested sub-agents
- Plans are surfaced in the Workflows page sidebar
- Policy checks can be inserted before plan emission
Each turn compares the current user input against the previous session goal using:
- Keyword scoring — explicit drift phrases ("actually", "instead", "on second thought", "new plan")
- Jaccard divergence — word set overlap between current and previous inputs
- Drift events fire when the combined score ≥ 0.4
- Events are stored in
lens_eventsand surfaced on the Workflows page "Goal Drift" tab
After normal reflection (when enableReflection is true), a second adversarial pass runs with a more critical system prompt:
- Actively hunts for missed edge cases, validation gaps, and security concerns
- Stored in
reflection_memorywith categoryadversarial - Critique cards shown on the Metacognition page
When metacognition suggests parallelize, the system can fan out to multiple sub-agents:
- Active sub-agent tasks tracked in
src/agent/sub-agent-tracker.ts - Task board visible on Workflows page under the Sub-Agents tab
- Shows running tasks (pulsing green dots) and recently completed tasks
- Auto-refreshes every 3 seconds while the tab is active
CortexPrism — Open-source agentic AI harness · MIT License · Built with Deno 2.x + TypeScript
- Agent Loop
- Metacognition
- Memory System
- Skills System
- Sub-Agents
- Built-in Tools
- Code Intelligence
- Code Sandbox
- Cross-Agent Context Protocol
- Prompt Lab
- PKM Assistant
- Voice Pipeline
- Computer Use
- Browser Tool
- Git & GitHub
- Scheduler & Jobs
- Dashboard
- Observability
- A2A Protocol
- MCP Gateway
- Distributed Nodes
- Memori Checkpoints
- Eval System
- Workflow Engine
- Triggers
- Projects
- TUI
- Glossary
- Update System