[ACTION:slug:{"params"}] tags emitted by the LLM in chat responses, strips them from the visible message, executes the corresponding flow, and streams status updates back to the user.
Why Action Runner?
Problem: Qwen-2.5 (and many uncensored models) struggle with reliable tool calling in AnythingLLM’s agent mode. Function calls often fail, get malformed, or hallucinate parameters. Solution: Instead of relying on native tool calling, the model emits structured text tags that trigger pre-built flows. The Action Runner plugin intercepts these tags, validates parameters, and executes multi-step workflows using a declarative JSON format.How It Works
1. Model Emission
The model outputs a special tag in its prose:2. Interception
The action-runner plugin:- Detects the
[ACTION:slug:{params}]pattern - Strips it from the visible chat response
- Parses the slug and JSON parameters
- Looks up the flow definition in
action_flowscollection
3. Execution
The plugin executes the flow’s steps sequentially:- Each step is one of 14 available step types
- Steps can use variables from previous steps via
{{step_name.field}} - Execution status is streamed back to the chat UI
- Results are logged to
agent_audits(success/error/miss)
4. Logging
Every ACTION execution is logged to theagent_audits collection:
success: Flow completed without errorserror: Flow failed (with error message)miss: Slug not found inaction_flows
Available Actions
Flow Definition Format
Flows are stored in theaction_flows Directus collection with this structure:
Step Types
The Action Runner supports 14 step types:MCP Tool Steps
Utility Steps
Variable Interpolation
Steps can reference variables from:{{params.fieldName}}— Input parameters from the ACTION tag{{stepName.field}}— Output from previous steps{{env.VARIABLE}}— Environment variables{{user.id}}— Current user context
System Prompt Integration
The GENIE_SYSTEM_PROMPT includes instructions for emitting ACTION tags:Error Handling
Flow Not Found
If the slug doesn’t exist inaction_flows, the runner logs a miss to agent_audits and returns an error message to the chat.
Step Failure
If a step throws an error:- Execution halts immediately
- Error is logged to
agent_auditswith full stack trace - User sees a friendly error message in chat
Tier Limits
If a step triggers a tier-gated operation (e.g.create-item on media_jobs), the Directus MCP server checks quotas and throws a tier_limit: error that propagates to the user.
Implementation Details
Plugin Location
server/utils/actionRunner/
Key Files
index.js— Main plugin entrypoint and tag interceptorexecutor.js— Flow step executorsteps/— Individual step type implementations
Integration Points
- Chat stream: Intercepts SSE stream from AnythingLLM
- Agent audits: Logs every execution to Directus
- MCP servers: Reuses existing MCP tool connections
Compared to Native Tool Calling
When to use Action Runner: Complex workflows, unreliable tool-calling models, need for audit trails
When to use native tools: Simple single-step operations, models with good function calling (GPT-4, Claude)
Related
- MCP Servers — The 29 tools available in flow steps
- Ollama Models — Models that emit ACTION tags
- Collection:
action_flows— Flow definitions (slug → steps JSON) - Collection:
agent_audits— Execution logs (success/error/miss)
