eslint-plugin-agentic-safety
ESLint plugin enforcing reliability and safety patterns for agentic AI codebases — catch the failure modes that silently break production AI agents
What It Catches
Agentic AI systems fail in ways traditional software doesn't. LLM calls silently return garbage, agent loops spin forever, fire-and-forget patterns lose critical results, and missing observability makes debugging impossible. This plugin catches these patterns at lint time — before they reach production.
Silent LLM Failures
LLM calls that swallow errors or ignore empty responses, causing downstream agents to operate on garbage data
Unbounded Loops
Agent retry and planning loops without iteration limits that burn tokens and hang indefinitely
Fire-and-Forget
Unhandled promises from agent calls whose results are silently discarded, losing critical outputs
Missing Observability
Agent operations without tracing or structured logging that make debugging production failures impossible
6 Safety Rules
Enforces timeout configuration on all LLM and agent API calls. Without timeouts, a hanging LLM provider can block your entire agent pipeline indefinitely.
// No timeout — hangs forever if
// provider is slow
const res = await openai.chat
.completions.create({
model: "gpt-4",
messages: [{ role: "user",
content: prompt }]
});const res = await openai.chat
.completions.create({
model: "gpt-4",
messages: [{ role: "user",
content: prompt }],
timeout: 30000
});Detects empty catch blocks on agent/LLM calls. Swallowed errors cause agents to silently proceed with missing data, producing downstream failures that are nearly impossible to trace.
try {
const res = await agent.run(task);
} catch (e) {
// silently swallowed
}try {
const res = await agent.run(task);
} catch (e) {
logger.error("Agent failed", { e });
throw new AgentError(e);
}Flags agent/LLM calls whose return value is not awaited or assigned. Fire-and-forget patterns silently discard results, losing critical agent outputs and error signals.
// Result discarded — agent output
// is silently lost
agent.run(task);
llm.complete(prompt);const result = await agent
.run(task);
const output = await llm
.complete(prompt);Detects while/for loops containing agent calls without explicit iteration limits. Unbounded agent loops burn tokens endlessly and can hang your entire system.
// No iteration limit — spins
// forever burning tokens
while (!done) {
result = await agent.run(task);
done = result.complete;
}const MAX_ITER = 10;
for (let i = 0; i < MAX_ITER; i++) {
result = await agent.run(task);
if (result.complete) break;
}Requires catch blocks handling agent errors to use structured error types instead of generic Error. Structured errors enable automated retry logic, error categorization, and proper observability.
} catch (e) {
throw new Error("agent failed");
}} catch (e) {
throw new AgentTimeoutError(
"agent failed", { cause: e }
);
}Requires agent functions to include tracing or structured logging calls. Without observability, debugging production agent failures becomes guesswork across opaque LLM call chains.
async function runAgent(task) {
// No tracing — opaque in prod
return await llm.complete(task);
}async function runAgent(task) {
const span = tracer
.startSpan("runAgent");
const res = await llm.complete(task);
span.end();
return res;
}Quick Start
npm install eslint-plugin-agentic-safety --save-dev// eslint.config.js
import agenticSafety from "eslint-plugin-agentic-safety";
export default [
agenticSafety.configs.recommended,
{
rules: {
"agentic-safety/require-agent-timeout": "error",
"agentic-safety/no-swallowed-agent-error": "error",
"agentic-safety/no-fire-and-forget-agent": "warn",
"agentic-safety/no-unbounded-agent-loop": "error",
"agentic-safety/require-structured-error": "warn",
"agentic-safety/require-agent-tracing": "warn"
}
}
];Customizing Agent Patterns
By default, the plugin detects common agent and LLM call patterns like openai.chat.completions.create, anthropic.messages.create, agent.run, and llm.complete. You can customize these patterns to match your codebase:
{
"rules": {
"agentic-safety/require-agent-timeout": ["error", {
"agentPatterns": ["myAgent.execute", "customLLM.call"],
"timeoutProperty": "requestTimeout"
}]
}
}