Brain & ReAct Loop
The brain is the reasoning engine that powers every Moxxy agent. It uses the ReAct (Reasoning + Acting) pattern to process requests and execute skills.
Overview
┌───────────────────────────────────────────────────────┐
│ Trigger Input │
│ (User message, channel event, etc.) │
└─────────────────────┬─────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ AutonomousBrain │
├───────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ LLM │───▶│ Parse │───▶│ Execute │ │
│ │ Call │ │ Invoke │ │ Skill │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │
│ │ ┌─────────┐ │ │
│ └────────▶│ Loop │◀─────────┘ │
│ │ (max 10)│ │
│ └─────────┘ │
│ │
└─────────────────────┬─────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────┐
│ Response Output │
│ (To user, channel, etc.) │
└───────────────────────────────────────────────────────┘The ReAct Pattern
ReAct combines reasoning and acting in an interleaved manner:
- Thought - Agent thinks about what to do
- Action - Agent invokes a skill
- Observation - System returns skill result
- Repeat - Continue until done
Example Flow
User: "Check if my website is up and notify me on Telegram if it's down"
--- Iteration 1 ---
LLM Response:
I need to check if the website is responding. I'll use the web_crawler skill.
<invoke name="web_crawler">["https://mywebsite.com"]</invoke>
System: Executes skill...
Observation:
HTTP 503 - Service Unavailable
--- Iteration 2 ---
LLM Response:
The website is down (503 error). I should notify the user on Telegram.
<invoke name="telegram_notify">["Alert: Your website is down with HTTP 503 error"]</invoke>
System: Executes skill...
Observation:
Message sent successfully
--- Iteration 3 ---
LLM Response:
I've checked your website and found it's currently down with a 503 error.
I've sent you a Telegram notification about this issue.
[Task complete - no more iterations needed]System Prompt
The brain uses a structured system prompt:
You are an autonomous AI agent running inside the moxxy framework.
You have SKILLS that let you take real actions on the host system.
RULES:
1. When the user asks you to DO something, use your skills via the
invocation format. Do NOT respond with code snippets.
2. For pure knowledge questions, respond directly.
3. Only use skills listed in AVAILABLE SKILLS.
4. Never tell the user to run commands manually — use host_shell.
5. After a skill result, present the result and STOP.
6. Be concise. Answer the question, present the result, done.
SKILL INVOCATION FORMAT:
<invoke name="skill_name">["arg1", "arg2"]</invoke>
Arguments MUST be a valid JSON array of strings.
--- AVAILABLE SKILLS ---
[skill catalog]
--- END OF SKILLS ---
--- AGENT PERSONA ---
[persona.md content]
--- END PERSONA ---Invocation Format
Basic Format
<invoke name="skill_name">["arg1", "arg2"]</invoke>With Object Parameters (MCP)
<invoke name="mcp_tool">{"param": "value", "other": 123}</invoke>Parsing Rules
- Skill name must match exactly
- Arguments must be valid JSON
- Only one invocation per response
- System captures and executes
Loop Control
Maximum Iterations
The loop runs for a maximum of 10 iterations per trigger:
const MAX_ITERATIONS: usize = 10;This prevents infinite loops.
[CONTINUE] Tag
For tasks requiring multiple skill calls, agents can append [CONTINUE]:
I've created the file. [CONTINUE]
<invoke name="host_shell">["chmod +x script.sh"]</invoke>This signals the system to continue processing.
Stop Conditions
The loop stops when:
- No
<invoke>tags in response - Maximum iterations reached
- Error occurs
- Agent indicates completion
Origin Handling
Different input sources are handled differently:
| Origin | Role | Session |
|---|---|---|
| WEB_UI | user | Persistent |
| TELEGRAM | user | Persistent |
| DISCORD | user | Persistent |
| MOBILE_APP | user | Persistent |
| LOCAL_TUI | user | Persistent |
| SYSTEM_CRON | system | Fresh |
| WEBHOOK | system | Fresh |
| SWARM_DELEGATION | system | Fresh |
Human vs System Origins
Human origins share a persistent conversation session:
- Messages are added to STM
- Context carries across messages
- Memory is updated
System origins get a fresh session:
- No prior context
- Isolated execution
- No memory contamination
Streaming
Brain responses can be streamed via Server-Sent Events (SSE):
const eventSource = new EventSource('/api/agents/default/chat/stream');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
// data.content contains incremental response
// data.done indicates completion
};Event Types
| Event | Description |
|---|---|
token | Text token generated |
invoke_start | Skill invocation starting |
invoke_end | Skill execution complete |
done | Response complete |
Context Building
Memory Injection
Before each LLM call, the brain injects context:
[Memory Context]
Previous conversation:
- User: Hello
- Agent: Hi there!
- User: What can you do?
Related memories:
- User prefers Python over JavaScript
- Working on project X
[/Memory Context]Skill Catalog
Available skills are listed in the system prompt:
--- AVAILABLE SKILLS ---
host_shell (v1.0.0)
Execute shell commands on the host system
Usage: <invoke name="host_shell">["command"]</invoke>
web_crawler (v1.0.0)
Fetch and parse web content
Usage: <invoke name="web_crawler">["url"]</invoke>
...
--- END OF SKILLS ---Error Handling
Skill Errors
When a skill fails:
Observation: ERROR: Command failed with exit code 1
stderr: permission deniedThe agent can:
- Try a different approach
- Ask for clarification
- Report the error to the user
LLM Errors
If the LLM call fails:
- Error is logged
- User is notified
- Gateway may restart agent
Timeout
Long-running operations timeout:
# Configure timeout (default: 60s)
moxxy run --agent default --prompt "Store '120' in vault as skill_timeout_seconds"Advanced Features
Multi-Step Tasks
For complex workflows:
User: "Set up a new project with git, create a README, and push to GitHub"
Agent plans:
1. Create directory structure
2. Initialize git
3. Create README
4. Add remote
5. Push
Each step is executed in sequence via the ReAct loop.Conditional Logic
Agents can make decisions:
I'll check the file first.
<invoke name="host_shell">["test -f config.json"]</invoke>
[If file exists]
The config exists. I'll read it...
<invoke name="host_shell">["cat config.json"]</invoke>
[If not]
The config doesn't exist. I'll create a default...
<invoke name="host_shell">["echo '{}' > config.json"]</invoke>Tool Chaining
Skills can be chained:
<invoke name="host_shell">["curl -s API_URL"]</invoke>
[Parse JSON response]
<invoke name="telegram_notify">["Result: ..."]</invoke>Debugging
View Brain Activity
moxxy logs | grep -i brainTrace Invocations
moxxy logs | grep -i invokeVerbose Mode
In dev mode, additional debug info is logged:
moxxy dev
moxxy logsConfiguration
Model Selection
Choose the LLM for each agent:
# Via vault
moxxy run --agent default --prompt "Store 'gpt-4o' in vault as llm_model"
# Or during init
moxxy initTemperature
Control response creativity:
moxxy run --agent default --prompt "Store '0.7' in vault as llm_temperature"Max Tokens
Limit response length:
moxxy run --agent default --prompt "Store '2048' in vault as llm_max_tokens"