Nexus uses a composable middleware pipeline for cross-cutting concerns. Middleware runs before and after the agent loop, enabling concerns like timing, security, budgeting, and logging without modifying core agent logic.
User Request
↓
[Middleware Chain]
↓
Agent Loop
↓
[Middleware Chain]
↓
Response
Tracks execution time for each agent turn:
timing()Outputs timing information to logs for performance monitoring.
Detects and blocks prompt injection attempts:
promptFirewall()Checks for 12 known injection patterns:
- System prompt override attempts
- Instruction injection
- Role confusion attacks
- Delimiter attacks
- And more
Enforces budget limits per session:
budgetEnforcer({ limitUsd: 2.0 })Tracks token usage and costs. Warns at 80% of budget, stops before exceeding limit.
Controls file and tool access:
permissionMiddleware(permissionGuard)Enforces path-based and tool-level permissions.
Controls network access:
networkMiddleware(networkGuard)Can deny access to private IP ranges, specific domains, etc.
Enables human-in-the-loop supervision:
supervisionMiddleware(supervisor)Requires approval for dangerous operations.
Detects anomalous behavior:
monitorMiddleware(monitor)Tracks patterns and alerts on suspicious activity.
Injects relevant memory into context:
memoryContextBuilder({ nexusHome: NEXUS_HOME })Searches wiki memory and injects relevant pages into context.
Records files, commands, and URLs as artifacts:
artifactTracker()Tracks all artifacts created during a session.
Truncates huge tool outputs:
toolCompactor()Prevents tool outputs from blowing context limits.
Scans outputs for sensitive information:
outputScanner()Detects and redacts API keys, passwords, etc.
Structured logging:
logger({ verbose: false })Logs all agent events in structured format.
Deterministic hooks that run after the agent loop:
afterAgent([
afterAgentHooks.noteFileChanges,
afterAgentHooks.archiveSessionToWiki({ nexusHome: NEXUS_HOME }),
afterAgentHooks.suggestCommitIfChanged,
])Create custom middleware by implementing the middleware interface:
import type { Middleware } from "@nexus/core";
const customMiddleware: Middleware = async (context, next) => {
// Before agent logic
console.log("Before agent:", context);
// Call next middleware
const result = await next(context);
// After agent logic
console.log("After agent:", result);
return result;
};Middleware runs in the order specified. Typical order:
middleware: [
timing(), // 1. Start timing
monitorMiddleware(monitor), // 2. Monitor behavior
promptFirewall(), // 3. Check for injection
memoryContextBuilder({ nexusHome }), // 4. Inject memory
budgetEnforcer({ limitUsd: BUDGET }), // 5. Check budget
permissionMiddleware(permissionGuard), // 6. Check permissions
networkMiddleware(networkGuard), // 7. Check network access
supervisionMiddleware(supervisor), // 8. Enable supervision
artifactTracker(), // 9. Track artifacts
toolCompactor(), // 10. Compact tool outputs
outputScanner(), // 11. Scan outputs
logger({ verbose: false }), // 12. Log events
afterAgent([ // 13. After-agent hooks
afterAgentHooks.noteFileChanges,
afterAgentHooks.archiveSessionToWiki({ nexusHome }),
afterAgentHooks.suggestCommitIfChanged,
]),
]Configure middleware in the agent config:
const agent = new NexusAgent({
config: {
middleware: [
timing(),
promptFirewall(),
budgetEnforcer({ limitUsd: 2.0 }),
// ... more middleware
],
},
provider,
});- Order matters — Middleware runs in the order specified
- Keep middleware focused — Each middleware should do one thing well
- Use existing middleware — Don't reinvent the wheel
- Test middleware — Ensure middleware doesn't break the agent loop
- Log appropriately — Use the logger middleware for debugging
Enable/disable middleware based on conditions:
const conditionalMiddleware = (enabled: boolean): Middleware => {
if (!enabled) {
return async (_, next) => next();
}
return promptFirewall();
};Compose multiple middleware into one:
const securityMiddleware = compose([
promptFirewall(),
permissionMiddleware(permissionGuard),
networkMiddleware(networkGuard),
]);Middleware can add context for subsequent middleware:
const contextMiddleware: Middleware = async (context, next) => {
context.customData = { timestamp: Date.now() };
return next(context);
};- Architecture — System architecture
- Security — Security features and best practices
- CLI Reference — CLI commands and options