Synthetic Injectors

Synthetic injectors are guardrails that fire at specific points in the assistant loop, injecting messages into the conversation to guide LLM behavior. They are implemented as Go plugin hooks interpreted by Yaegi. Example injectors are available in the repository under .aura/plugins/injectors/ — they are not installed by aura init.

Timing

Each injector fires at one of nine points in the assistant loop:

Timing When
BeforeChat Before sending messages to the LLM
AfterResponse After receiving the LLM response
BeforeToolExecution Before a tool call executes (can modify args or block)
AfterToolExecution After a tool call completes (can modify output)
OnError When the LLM provider returns an error (after built-in recovery exhausted). Can classify, retry, or suppress errors.
BeforeCompaction Before context compaction begins. Can skip built-in compaction (plugin manages context itself).
AfterCompaction After context compaction completes (success or failure). Read-only — observe but don’t modify results.
OnAgentSwitch When the active agent changes. Read-only — observe but don’t modify the switch. Reason: user, failover, task, cycle, resume.
TransformMessages Inside chat(), transforms message array before LLM call. Ephemeral — builder history untouched.

Shipped Injector Plugins

Plugin Timing Purpose
todo-reminder BeforeChat Reminds about pending todos every N iterations
max-steps BeforeChat Disables tools when iteration limit reached
session-stats BeforeChat Shows session stats summary (turns, tool calls, context usage, top tools) as a Notice every 5 turns
todo-not-finished AfterResponse Warns if todos incomplete and no tool calls
empty-response AfterResponse Handles empty LLM responses
done-reminder AfterResponse Reminds LLM to call Done tool when stopping
loop-detection AfterToolExecution Detects repeated identical tool calls
failure-circuit-breaker AfterToolExecution Stops after 3+ consecutive different tool failures
repeated-patch AfterToolExecution Warns after 5+ patches to same file

Example injectors are available in the repository under .aura/plugins/injectors/. Copy them to your own .aura/plugins/ directory, then edit the Go source to customize detection logic and message text. Disable any injector by setting disabled: true in its plugin.yaml.

Condition System

Injectors use a condition expression in plugin.yaml to control when they fire. The condition is evaluated before every hook call.

# plugin.yaml
condition: "auto and context_above:70"
once: false

Boolean Conditions

Condition True when
auto Auto mode is enabled
todo_empty No todo items exist
todo_done All todo items completed
todo_pending Pending or in-progress items exist

Comparison Conditions

Greater-than Less-than Compares
context_above:<N> context_below:<N> Token usage percentage
history_gt:<N> history_lt:<N> Message count
tool_errors_gt:<N> tool_errors_lt:<N> Tool error count
tool_calls_gt:<N> tool_calls_lt:<N> Tool call count
turns_gt:<N> turns_lt:<N> LLM turn count
compactions_gt:<N> compactions_lt:<N> Compaction count
iteration_gt:<N> iteration_lt:<N> Current iteration
tokens_total_gt:<N> tokens_total_lt:<N> Cumulative tokens (input + output)
model_context_gt:<N> model_context_lt:<N> Model max context tokens
model_params_gt:<N> model_params_lt:<N> Model parameters in billions (supports decimals like 0.5)

Model parameter and context conditions return false when the model is unresolved (zero values), preventing false positives like model_params_lt:10 matching before model resolution.

Model Conditions

Condition True when
model_has:vision Model supports vision/image input
model_has:tools Model supports tool calling
model_has:thinking Model supports reasoning output
model_has:thinking_levels Model supports thinking effort levels (low/medium/high)
model_has:embedding Model supports text embeddings
model_has:reranking Model supports reranking
model_has:context_override Model supports context length override
model_is:<name> Model name matches (case-insensitive)

Filesystem & Shell Conditions

Condition True when
exists:<path> File or directory exists (relative to CWD or absolute)
bash:<cmd> Shell command exits 0 (120s timeout)

Negation

Prefix any condition with not to negate it:

condition: "not auto"
condition: "not todo_done"

Composition

Join conditions with and – all must be true:

condition: "auto and context_above:70"
condition: "todo_pending and not turns_gt:50"
condition: "model_has:tools and model_params_gt:10"

Trigger Control

Set once: true in plugin.yaml to fire the injector only on the first match. Once the condition evaluates to true and the hook fires, it will not fire again for the rest of the session. The once state is preserved across /reload.

condition: "context_above:90"
once: true

Diagnostic Plugins

Two example diagnostic plugins are available alongside the injectors. These are not injectors themselves but use the same plugin hook system:

Plugin Type Purpose
tool-logger Hook Logs every tool call and result to a file
turn-tracker Hook Injects a status line every N turns with token and context info

Example diagnostics are available in the repository under .aura/plugins/diagnostics/.

Intent-Based Query Methods

The Messages type exposes intent-based methods that filter by semantic role, not by type value. Consumers use these rather than filtering on Type directly:

Method What it returns
ForLLM() Messages sent to the primary LLM. Excludes DisplayOnly, Bookmark, Metadata. Includes Normal, Synthetic, Ephemeral.
ForCompaction(maxLen) Messages sent to the compaction LLM. Excludes Synthetic, Ephemeral, internal types, and all thinking content. Tool results truncated to maxLen.
ForPreservation() Messages retained after compaction. Normal only — all one-turn and internal types removed.
ForSave() Messages persisted in session files. Excludes Ephemeral. Includes Normal, Synthetic, DisplayOnly, Bookmark, Metadata.
ForExport() Messages for human-readable export (plaintext, markdown). Excludes Synthetic, Ephemeral, Metadata.
ForExportStructured() Messages for machine-readable export (JSON, JSONL). Excludes Synthetic, Ephemeral. Includes Metadata.
ForDisplay() Messages for UI rendering on session restore. Excludes System role, Tool role, Metadata.

Customization

Users customize injectors by editing the plugin source in their .aura/plugins/injectors/ directory. Each injector is a standalone Go module with a main.go containing the hook function and a plugin.yaml with metadata and conditions.

To create a custom injector, add a new plugin directory under .aura/plugins/ with a BeforeChat, AfterResponse, BeforeToolExecution, AfterToolExecution, OnError, BeforeCompaction, AfterCompaction, OnAgentSwitch, or TransformMessages hook function. See Plugins for the full plugin authoring guide.


Back to top

Copyright © 2026 idelchi. Distributed under the MIT License.