skills/verify-patterns/SKILL.md
Verify AI agent patterns including loop safety, retry limits, tool consistency, context size, and graph cycle analysis. Use when asked to "verify agent patterns", "check loops", "verify tools", or "check retry limits".
npx skillsauth add aurite-ai/agent-verifier verify-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Verify AI agent code for common anti-patterns that can cause infinite loops, runaway retries, tool mismatches, and context overflow. All analysis happens locally.
Trigger this skill when the user asks to:
Note: For full verification including security, quality, and language-specific checks, tell the user to say "verify agent".
Identify the agent framework by checking imports in Python/TypeScript files:
| Import Pattern | Framework |
|----------------|-----------|
| from langgraph or import langgraph | LangGraph |
| from crewai or import crewai | CrewAI |
| from autogen or import autogen | AutoGen |
| from langchain or import langchain | LangChain |
| Direct openai/anthropic SDK only | Custom |
Also check for framework config files: langgraph.json, crew.yaml.
Find files to analyze:
Priority files:
graph.py, graph.ts - Agent workflow definitionstools.py, tools.ts, tools/*.py, tools/*.ts - Tool implementationsstate.py, state.ts - State schemasprompts.py, prompts/*.md, system.md - Prompt templatesagent.py, agent.ts - Main agent logicDirectories to check:
src/agent/, agent/, src/, project rootlib/, app/, packages/Exclude from analysis:
skills/ directory — these are skill definitions, not agent system prompts[PATTERN] — Mechanical check. Apply exactly as written.[HEURISTIC] — Judgment required. Mark findings clearly.Tag every finding with [P] for pattern or [H] for heuristic.
[PATTERN] Loop SafetyApply mechanically. Do not pass a loop because it "looks like it might terminate."
| Pattern to find | Pass condition | Severity |
|-----------------|----------------|----------|
| while True: in Python | A break statement exists within the same block scope | ⚠️ Warning if absent |
| for { } in Go | A break or return exists within the block | ⚠️ Warning if absent |
| while (true) in TS/JS | A break or return exists within the block | ⚠️ Warning if absent |
| Function calls itself recursively | A non-recursive return path exists (base case), OR a depth/counter parameter is present | ⚠️ Warning if absent |
[HEURISTIC] Fallback: Unrecognized Loop Patterns
After applying the pattern table, also scan for:
yield indefinitely without documented exitFlag as ⚠️ Warning: "Potential unbounded loop not matching known patterns — verify termination condition manually"
[PATTERN] Retry Limit EnforcementApply mechanically. If required parameter is absent, flag as ❌ Issue.
Python — Decorator-based:
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| @retry (tenacity) | stop=stop_after_attempt(n) or stop=stop_after_delay(n) | stop= absent |
| @backoff.on_exception | max_tries=n | max_tries= absent |
Python — HTTP client retry:
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| urllib3.Retry(...) | total=n where n > 0 | total= absent or total=0 |
| HTTPAdapter(max_retries=Retry(...)) | Retry object must have total=n | total= absent |
| httpx.HTTPTransport(retries=n) | retries=n where n > 0 | retries= absent or retries=0 |
Python — AWS SDK (boto3):
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| Config(retries={...}) | max_attempts > 1 | max_attempts absent or ≤ 1 |
Note: boto3 without explicit retry config uses SDK defaults (3 attempts) — do not flag absence.
JavaScript/TypeScript:
| Library/Pattern | Required parameter | Fail condition |
|-----------------|-------------------|----------------|
| retry(...) (async-retry) | retries: n in options | retries: absent |
| pRetry(...) (p-retry) | retries: n in options | retries: absent |
Custom retry loops (all languages):
| Pattern to find | Pass condition | Fail condition |
|-----------------|----------------|----------------|
| Loop + try/except + continue | Integer counter with max check | No counter → ❌ Issue |
[HEURISTIC] Fallback: Unrecognized Retry Patterns
After applying pattern tables, scan for:
stamina, aiohttp_retry)max_retries, retry_count, attemptsFlag as ⚠️ Warning: "Potential retry pattern not matching known libraries — verify retry bounds manually"
[PATTERN] Tool Registry ConsistencyStep 1: Collect defined tools
Scan tool definition files. A name found by any pattern counts as registered.
Python — decorator patterns:
| Pattern | How to extract name |
|---------|---------------------|
| @tool (LangChain) on def | Function name below decorator |
| @function_tool (OpenAI Agents SDK) on def | Function name below decorator |
| @tool(name="...") | Use name= argument value |
Python — dict/list patterns:
| Pattern | How to extract name |
|---------|---------------------|
| {"type": "function", "function": {"name": "..."}} (OpenAI) | Value of "name" inside "function" |
| {"name": "...", "input_schema": {...}} (Anthropic) | Top-level "name" |
| {"name": "...", "description": "...", "parameters": {...}} | Top-level "name" |
| ToolNode([func1, func2, ...]) (LangGraph) | Each function name in list |
| tools = [func1, func2] / TOOLS = [...] | Each identifier in list |
TypeScript/JavaScript:
| Pattern | How to extract name |
|---------|---------------------|
| { type: "function", function: { name: "..." } } (OpenAI) | name: inside function: |
| tool({ description: "...", parameters: z.object({...}) }) | The const variable name |
| new DynamicTool({ name: "...", ... }) (LangChain.js) | Value of name: |
| zodFunction({ name: "...", ... }) | Value of name: |
Step 2: Collect tool references from prompts
Scan .md, .txt, prompts.py for backtick-quoted identifiers naming capabilities.
Step 3: Cross-reference
| Finding | Severity | |---------|----------| | Reference not in definition list | ❌ Issue (hallucinated tool) | | Defined tool not in any prompt | ⚠️ Warning (undocumented tool) |
[HEURISTIC] Tools never bound to LLM
Find where tools are defined and where LLM is invoked. If tools exist but are never connected to the LLM call, flag as ❌ Issue: "Tools defined but never connected to LLM invocation"
[HEURISTIC] Fallback: Unrecognized Tool Definitions
Scan for tool-like structures:
"description" and "parameters" keystools, tool_list, available_tools, functionsrun(), execute(), or __call__() methodsInclude in count and note: "Tool detected via heuristic — verify this is an intended agent tool."
[PATTERN] Context Size AwarenessFormula: token_estimate = len(file_content_chars) / 4
| Content | ⚠️ Warning threshold | ❌ Issue threshold | |---------|----------------------|-------------------| | System prompt file | > 4,000 tokens | > 8,000 tokens | | Single tool description | > 500 tokens | > 1,000 tokens | | All tool descriptions combined | > 2,000 tokens | > 4,000 tokens |
Exclude: skills/ directories (loaded on demand, not embedded)
[HEURISTIC] Fallback: Borderline and Non-Standard
.format()) → flag if template alone is large[HEURISTIC] Explicit Tool ListingCheck system prompts for:
Flag if tools are defined but not documented in system prompt.
[PATTERN] LangGraph Graph Cycle Analysis(Only when LangGraph is detected)
Detection steps:
a. Find graph file (graph.py, graph.ts, or file with StateGraph/MessageGraph)
b. Build edge map:
workflow.add_edge(source, dest) — unconditional edgeworkflow.add_conditional_edges(source, fn, mapping) — extract destinations from mappingc. Identify cycles: nodes reachable from themselves
d. For each cycle, check if END (or "__end__") is reachable via conditional edge
| Condition | Severity |
|-----------|----------|
| Cycle exists, END reachable via conditional | ✅ Pass |
| Cycle exists, no path to END | ❌ Issue |
| Graph has no END node | ❌ Issue |
| Node has no outgoing edges and is not END | ⚠️ Warning (dead-end) |
Example — infinite cycle (❌ Issue):
workflow.add_edge("agent", "tools")
workflow.add_edge("tools", "agent") # no path to END
Example — cycle with exit (✅ Pass):
workflow.add_conditional_edges("agent", should_continue, {
"continue": "tools",
"end": END
})
workflow.add_edge("tools", "agent")
[HEURISTIC] Fallback: Non-LangGraph Graphs
Scan for graph-like control flow:
Flag as ⚠️ Warning: "Potential cyclic control flow — verify termination condition exists"
# Agent Pattern Verification Report
**Project:** [name or path]
**Date:** [current date]
**Framework detected:** [LangGraph | CrewAI | AutoGen | LangChain | Custom | None]
**Files analyzed:** [count]
## Summary
✅ X checks passed | ⚠️ Y warnings | ❌ Z issues
## Loop Safety
- [x] All loops have termination conditions
- [ ] ⚠️ Potential unbounded loop at `[file:line]`
## Retry Limits
- [x] All retry mechanisms have explicit limits
- [ ] ❌ Missing retry limit at `[file:line]`
## Tool Consistency
- [x] Tool registry found: X tools defined
- [ ] ❌ Y hallucinated tool references
- [ ] ⚠️ Z undocumented tools
## Context Size
- [x] System prompt within limits (~X tokens)
- [ ] ⚠️ System prompt exceeds recommended size
## Findings
> `[P]` = pattern-matched · `[H]` = heuristic
### ✅ Passing
- `[P]` [Check]: [confirmation]
### ⚠️ Warnings
- `[P|H]` [Check]: [description]
- **Location:** [file:line]
- **Suggestion:** [how to fix]
### ❌ Issues
- `[P|H]` [Check]: [description]
- **Location:** [file:line]
- **Rule:** [which rule violated]
- **Fix:** [specific remediation]
## Recommendations
1. [Priority recommendation]
2. [Additional improvements]
For full verification including security, quality, and language-specific checks, say "verify agent".
development
Verify code for security issues including hardcoded secrets, input validation, error exposure, and dependency vulnerabilities. Use when asked to "verify security", "check for secrets", or "scan for vulnerabilities".
development
Verify code quality including naming conventions, organization, documentation, and general best practices. Use when asked to "verify quality", "check code quality", or "review code organization".
development
Language-specific verification for Python, TypeScript/JavaScript, and Go. Checks type safety, language idioms, and best practices. Use when asked to "verify language", "check types", or for language-specific checks.
testing
Full agent verification suite. Runs security, patterns, quality, and language-specific checks. Use when asked to "verify agent", "verify my agent", "audit agent", or "full verification".