@aryaminus/controlkeel-opencode 0.3.12 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/skills/agent-integration/SKILL.md +21 -0
- package/.opencode/skills/agent-pattern-verification/SKILL.md +355 -0
- package/.opencode/skills/agent-pattern-verification/references/pattern-checklist.md +501 -0
- package/.opencode/skills/align/SKILL.md +24 -2
- package/.opencode/skills/benchmark-operator/SKILL.md +21 -0
- package/.opencode/skills/compliance-audit/SKILL.md +21 -0
- package/.opencode/skills/controlkeel-governance/SKILL.md +22 -1
- package/.opencode/skills/cost-optimization/SKILL.md +21 -0
- package/.opencode/skills/domain-audit/SKILL.md +21 -0
- package/.opencode/skills/handoff/SKILL.md +21 -0
- package/.opencode/skills/plan-slice/SKILL.md +44 -5
- package/.opencode/skills/policy-training/SKILL.md +21 -0
- package/.opencode/skills/proof-memory/SKILL.md +21 -0
- package/.opencode/skills/security-review/SKILL.md +79 -6
- package/.opencode/skills/security-review/references/anti-rationalization-patterns.md +59 -0
- package/.opencode/skills/ship-readiness/SKILL.md +21 -0
- package/package.json +1 -1
|
@@ -11,6 +11,27 @@ compatibility:
|
|
|
11
11
|
- copilot-plugin
|
|
12
12
|
- github-repo
|
|
13
13
|
- open-standard
|
|
14
|
+
- cline-native
|
|
15
|
+
- cursor-native
|
|
16
|
+
- windsurf-native
|
|
17
|
+
- continue-native
|
|
18
|
+
- letta-code-native
|
|
19
|
+
- pi-native
|
|
20
|
+
- roo-native
|
|
21
|
+
- goose-native
|
|
22
|
+
- opencode-native
|
|
23
|
+
- gemini-cli-native
|
|
24
|
+
- kiro-native
|
|
25
|
+
- kilo-native
|
|
26
|
+
- amp-native
|
|
27
|
+
- augment-native
|
|
28
|
+
- hermes-native
|
|
29
|
+
- multica-native
|
|
30
|
+
- openclaw-native
|
|
31
|
+
- devin-terminal-native
|
|
32
|
+
- warp-native
|
|
33
|
+
- droid-bundle
|
|
34
|
+
- forge-acp
|
|
14
35
|
disable-model-invocation: true
|
|
15
36
|
metadata:
|
|
16
37
|
author: controlkeel
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-pattern-verification
|
|
3
|
+
description: "Verify AI agent code for dangerous patterns including infinite loops, unbounded retries, tool hallucinations, and context overflow. Use before deploying agent workflows or when reviewing agent code."
|
|
4
|
+
when_to_use: "Activate when reviewing agent code, before deploying LangGraph/CrewAI/AutoGen workflows, or when the user asks about agent safety, loops, retries, or tool consistency."
|
|
5
|
+
argument-hint: "[agent directory or files to verify]"
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
compatibility:
|
|
8
|
+
- codex
|
|
9
|
+
- claude-standalone
|
|
10
|
+
- claude-plugin
|
|
11
|
+
- copilot-plugin
|
|
12
|
+
- github-repo
|
|
13
|
+
- open-standard
|
|
14
|
+
- cline-native
|
|
15
|
+
- cursor-native
|
|
16
|
+
- windsurf-native
|
|
17
|
+
- continue-native
|
|
18
|
+
- letta-code-native
|
|
19
|
+
- pi-native
|
|
20
|
+
- roo-native
|
|
21
|
+
- goose-native
|
|
22
|
+
- opencode-native
|
|
23
|
+
- gemini-cli-native
|
|
24
|
+
- kiro-native
|
|
25
|
+
- kilo-native
|
|
26
|
+
- amp-native
|
|
27
|
+
- augment-native
|
|
28
|
+
- hermes-native
|
|
29
|
+
- multica-native
|
|
30
|
+
- openclaw-native
|
|
31
|
+
- devin-terminal-native
|
|
32
|
+
- warp-native
|
|
33
|
+
- droid-bundle
|
|
34
|
+
- forge-acp
|
|
35
|
+
metadata:
|
|
36
|
+
author: controlkeel
|
|
37
|
+
version: "1.0"
|
|
38
|
+
category: security
|
|
39
|
+
ck_mcp_tools:
|
|
40
|
+
- ck_context
|
|
41
|
+
- ck_validate
|
|
42
|
+
- ck_finding
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# Agent Pattern Verification Skill
|
|
46
|
+
|
|
47
|
+
Verify AI agent code for common anti-patterns that can cause infinite loops, runaway retries, tool mismatches, and context overflow. This skill complements ControlKeel's security and compliance validation with agent-specific pattern detection.
|
|
48
|
+
|
|
49
|
+
## When to Use
|
|
50
|
+
|
|
51
|
+
Trigger this skill when:
|
|
52
|
+
- Reviewing agent code before deployment
|
|
53
|
+
- Validating LangGraph, CrewAI, AutoGen, or LangChain workflows
|
|
54
|
+
- User asks about "agent safety", "infinite loops", "retry limits", or "tool consistency"
|
|
55
|
+
- Before merging agent workflow changes
|
|
56
|
+
|
|
57
|
+
## Verification Flow
|
|
58
|
+
|
|
59
|
+
1. **Call `ck_context`** to load the session context, risk tier, and existing findings
|
|
60
|
+
2. **Detect agent framework** by scanning imports and configuration files
|
|
61
|
+
3. **Run pattern checks** using the checklist below
|
|
62
|
+
4. **Persist findings** with `ck_finding` for each issue discovered
|
|
63
|
+
5. **Generate structured report** with pattern-matched vs heuristic tagging
|
|
64
|
+
|
|
65
|
+
## Pattern Checks
|
|
66
|
+
|
|
67
|
+
All checks are classified as:
|
|
68
|
+
- `[PATTERN]` - Mechanical check, high reliability (applied exactly as specified)
|
|
69
|
+
- `[HEURISTIC]` - Judgment-based, best-effort (requires interpretation)
|
|
70
|
+
|
|
71
|
+
### 1. Loop Safety `[PATTERN]`
|
|
72
|
+
|
|
73
|
+
Apply mechanically. Do not pass a loop because it "looks like it might terminate."
|
|
74
|
+
|
|
75
|
+
| Pattern to find | Pass condition | Severity |
|
|
76
|
+
|-----------------|----------------|----------|
|
|
77
|
+
| `while True:` in Python | A `break` statement exists within the same block scope | ⚠️ Warning if absent |
|
|
78
|
+
| `for { }` in Go | A `break` or `return` exists within the block | ⚠️ Warning if absent |
|
|
79
|
+
| `while (true)` in TypeScript/JavaScript | A `break` or `return` exists within the block | ⚠️ Warning if absent |
|
|
80
|
+
| Recursive function calls | A non-recursive return path exists (base case), OR a depth/counter parameter is present | ⚠️ Warning if absent |
|
|
81
|
+
|
|
82
|
+
**Heuristic Fallback**: After applying pattern table, scan for:
|
|
83
|
+
- Loops where termination depends entirely on external/runtime state with no timeout
|
|
84
|
+
- Generator functions that `yield` indefinitely without documented exit
|
|
85
|
+
- Event/polling loops without timeout parameters
|
|
86
|
+
- Recursive call chains across multiple functions without depth tracking
|
|
87
|
+
|
|
88
|
+
Flag as ⚠️ Warning: *"Potential unbounded loop not matching known patterns — verify termination condition manually"*
|
|
89
|
+
|
|
90
|
+
### 2. Retry Limit Enforcement `[PATTERN]`
|
|
91
|
+
|
|
92
|
+
Apply mechanically. If required parameter is absent, flag as ❌ Issue.
|
|
93
|
+
|
|
94
|
+
**Python — Decorator-based:**
|
|
95
|
+
|
|
96
|
+
| Library/Pattern | Required parameter | Fail condition |
|
|
97
|
+
|-----------------|-------------------|----------------|
|
|
98
|
+
| `@retry` (tenacity) | `stop=stop_after_attempt(n)` or `stop=stop_after_delay(n)` | `stop=` absent |
|
|
99
|
+
| `@backoff.on_exception` | `max_tries=n` | `max_tries=` absent |
|
|
100
|
+
|
|
101
|
+
**Python — HTTP client retry:**
|
|
102
|
+
|
|
103
|
+
| Library/Pattern | Required parameter | Fail condition |
|
|
104
|
+
|-----------------|-------------------|----------------|
|
|
105
|
+
| `urllib3.Retry(...)` | `total=n` where n > 0 | `total=` absent or `total=0` |
|
|
106
|
+
| `HTTPAdapter(max_retries=Retry(...))` | Retry object must have `total=n` | `total=` absent |
|
|
107
|
+
| `httpx.HTTPTransport(retries=n)` | `retries=n` where n > 0 | `retries=` absent or `retries=0` |
|
|
108
|
+
|
|
109
|
+
**Python — AWS SDK (boto3):**
|
|
110
|
+
|
|
111
|
+
| Library/Pattern | Required parameter | Fail condition |
|
|
112
|
+
|-----------------|-------------------|----------------|
|
|
113
|
+
| `Config(retries={...})` | `max_attempts` > 1 | `max_attempts` absent or ≤ 1 |
|
|
114
|
+
|
|
115
|
+
> Note: boto3 without explicit retry config uses SDK defaults (3 attempts) — do not flag absence.
|
|
116
|
+
|
|
117
|
+
**JavaScript/TypeScript:**
|
|
118
|
+
|
|
119
|
+
| Library/Pattern | Required parameter | Fail condition |
|
|
120
|
+
|-----------------|-------------------|----------------|
|
|
121
|
+
| `retry(...)` (async-retry) | `retries: n` in options | `retries:` absent |
|
|
122
|
+
| `pRetry(...)` (p-retry) | `retries: n` in options | `retries:` absent |
|
|
123
|
+
|
|
124
|
+
**Custom retry loops (all languages):**
|
|
125
|
+
|
|
126
|
+
| Pattern to find | Pass condition | Fail condition |
|
|
127
|
+
|-----------------|----------------|----------------|
|
|
128
|
+
| Loop + `try/except` + `continue` | Integer counter with max check | No counter → ❌ Issue |
|
|
129
|
+
|
|
130
|
+
**Heuristic Fallback**: Scan for:
|
|
131
|
+
- Functions/decorators with "retry" in name not in tables above
|
|
132
|
+
- Imported modules with "retry" in package name (e.g. `stamina`, `aiohttp_retry`)
|
|
133
|
+
- Loops with sleep + exception handling + re-invocation without visible counter
|
|
134
|
+
- Config keys like `max_retries`, `retry_count`, `attempts`
|
|
135
|
+
|
|
136
|
+
Flag as ⚠️ Warning: *"Potential retry pattern not matching known libraries — verify retry bounds manually"*
|
|
137
|
+
|
|
138
|
+
### 3. Tool Registry Consistency `[PATTERN]`
|
|
139
|
+
|
|
140
|
+
**Step 1: Collect defined tools**
|
|
141
|
+
|
|
142
|
+
Scan tool definition files. A name found by any pattern counts as registered.
|
|
143
|
+
|
|
144
|
+
*Python — decorator patterns:*
|
|
145
|
+
|
|
146
|
+
| Pattern | How to extract name |
|
|
147
|
+
|---------|---------------------|
|
|
148
|
+
| `@tool` (LangChain) on `def` | Function name below decorator |
|
|
149
|
+
| `@function_tool` (OpenAI Agents SDK) on `def` | Function name below decorator |
|
|
150
|
+
| `@tool(name="...")` | Use `name=` argument value |
|
|
151
|
+
|
|
152
|
+
*Python — dict/list patterns:*
|
|
153
|
+
|
|
154
|
+
| Pattern | How to extract name |
|
|
155
|
+
|---------|---------------------|
|
|
156
|
+
| `{"type": "function", "function": {"name": "..."}}` (OpenAI) | Value of `"name"` inside `"function"` |
|
|
157
|
+
| `{"name": "...", "input_schema": {...}}` (Anthropic) | Top-level `"name"` |
|
|
158
|
+
| `{"name": "...", "description": "...", "parameters": {...}}` | Top-level `"name"` |
|
|
159
|
+
| `ToolNode([func1, func2, ...])` (LangGraph) | Each function name in list |
|
|
160
|
+
| `tools = [func1, func2]` / `TOOLS = [...]` | Each identifier in list |
|
|
161
|
+
|
|
162
|
+
*TypeScript/JavaScript:*
|
|
163
|
+
|
|
164
|
+
| Pattern | How to extract name |
|
|
165
|
+
|---------|---------------------|
|
|
166
|
+
| `{ type: "function", function: { name: "..." } }` (OpenAI) | `name:` inside `function:` |
|
|
167
|
+
| `tool({ description: "...", parameters: z.object({...}) })` | The `const` variable name |
|
|
168
|
+
| `new DynamicTool({ name: "...", ... })` (LangChain.js) | Value of `name:` |
|
|
169
|
+
| `zodFunction({ name: "...", ... })` | Value of `name:` |
|
|
170
|
+
|
|
171
|
+
**Step 2: Collect tool references from prompts**
|
|
172
|
+
|
|
173
|
+
Scan `.md`, `.txt`, `prompts.py` for backtick-quoted identifiers naming capabilities.
|
|
174
|
+
|
|
175
|
+
**Step 3: Cross-reference**
|
|
176
|
+
|
|
177
|
+
| Finding | Severity |
|
|
178
|
+
|---------|----------|
|
|
179
|
+
| Reference not in definition list | ❌ Issue (hallucinated tool) |
|
|
180
|
+
| Defined tool not in any prompt | ⚠️ Warning (undocumented tool) |
|
|
181
|
+
|
|
182
|
+
**Heuristic**: 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"*
|
|
183
|
+
|
|
184
|
+
**Heuristic Fallback**: Scan for tool-like structures:
|
|
185
|
+
- Dicts with both `"description"` and `"parameters"` keys
|
|
186
|
+
- Functions with structured docstrings (name, params, return)
|
|
187
|
+
- Variables named `tools`, `tool_list`, `available_tools`, `functions`
|
|
188
|
+
- Classes with `run()`, `execute()`, or `__call__()` methods
|
|
189
|
+
|
|
190
|
+
Include in count and note: *"Tool detected via heuristic — verify this is an intended agent tool."*
|
|
191
|
+
|
|
192
|
+
### 4. Context Size Awareness `[PATTERN]`
|
|
193
|
+
|
|
194
|
+
Formula: `token_estimate = len(file_content_chars) / 4`
|
|
195
|
+
|
|
196
|
+
| Content | ⚠️ Warning threshold | ❌ Issue threshold |
|
|
197
|
+
|---------|----------------------|-------------------|
|
|
198
|
+
| System prompt file | > 4,000 tokens | > 8,000 tokens |
|
|
199
|
+
| Single tool description | > 500 tokens | > 1,000 tokens |
|
|
200
|
+
| All tool descriptions combined | > 2,000 tokens | > 4,000 tokens |
|
|
201
|
+
|
|
202
|
+
**Exclude**: `skills/` directories (loaded on demand, not embedded)
|
|
203
|
+
|
|
204
|
+
**Heuristic Fallback**:
|
|
205
|
+
- Estimates within 20% of threshold → flag with tokenizer recommendation
|
|
206
|
+
- Dynamic prompts (f-strings, `.format()`) → flag if template alone is large
|
|
207
|
+
- Multiple concatenated prompts → estimate combined size
|
|
208
|
+
- Prompts with includes → note effective size may be larger
|
|
209
|
+
|
|
210
|
+
### 5. LangGraph Graph Cycle Analysis `[PATTERN]`
|
|
211
|
+
|
|
212
|
+
*(Only when LangGraph is detected)*
|
|
213
|
+
|
|
214
|
+
**Detection steps:**
|
|
215
|
+
a. Find graph file (`graph.py`, `graph.ts`, or file with `StateGraph`/`MessageGraph`)
|
|
216
|
+
b. Build edge map:
|
|
217
|
+
- `workflow.add_edge(source, dest)` — unconditional edge
|
|
218
|
+
- `workflow.add_conditional_edges(source, fn, mapping)` — extract destinations from mapping
|
|
219
|
+
c. Identify cycles: nodes reachable from themselves
|
|
220
|
+
d. For each cycle, check if `END` (or `"__end__"`) is reachable via conditional edge
|
|
221
|
+
|
|
222
|
+
| Condition | Severity |
|
|
223
|
+
|-----------|----------|
|
|
224
|
+
| Cycle exists, `END` reachable via conditional | ✅ Pass |
|
|
225
|
+
| Cycle exists, no path to `END` | ❌ Issue |
|
|
226
|
+
| Graph has no `END` node | ❌ Issue |
|
|
227
|
+
| Node has no outgoing edges and is not `END` | ⚠️ Warning (dead-end) |
|
|
228
|
+
|
|
229
|
+
## Framework Detection
|
|
230
|
+
|
|
231
|
+
Identify the agent framework by checking imports:
|
|
232
|
+
|
|
233
|
+
| Import Pattern | Framework |
|
|
234
|
+
|----------------|-----------|
|
|
235
|
+
| `from langgraph` or `import langgraph` | LangGraph |
|
|
236
|
+
| `from crewai` or `import crewai` | CrewAI |
|
|
237
|
+
| `from autogen` or `import autogen` | AutoGen |
|
|
238
|
+
| `from langchain` or `import langchain` | LangChain |
|
|
239
|
+
| Direct `openai`/`anthropic` SDK only | Custom |
|
|
240
|
+
|
|
241
|
+
Also check for framework config files: `langgraph.json`, `crew.yaml`.
|
|
242
|
+
|
|
243
|
+
## File Discovery
|
|
244
|
+
|
|
245
|
+
**Priority files:**
|
|
246
|
+
- `graph.py`, `graph.ts` - Agent workflow definitions
|
|
247
|
+
- `tools.py`, `tools.ts`, `tools/*.py`, `tools/*.ts` - Tool implementations
|
|
248
|
+
- `state.py`, `state.ts` - State schemas
|
|
249
|
+
- `prompts.py`, `prompts/*.md`, `system.md` - Prompt templates
|
|
250
|
+
- `agent.py`, `agent.ts` - Main agent logic
|
|
251
|
+
|
|
252
|
+
**Directories to check:**
|
|
253
|
+
- `src/agent/`, `agent/`, `src/`, project root
|
|
254
|
+
- `lib/`, `app/`, `packages/`
|
|
255
|
+
|
|
256
|
+
**Exclude from analysis:**
|
|
257
|
+
- `skills/` directory — these are skill definitions, not agent system prompts
|
|
258
|
+
|
|
259
|
+
## Report Format
|
|
260
|
+
|
|
261
|
+
Generate a structured report with the following format:
|
|
262
|
+
|
|
263
|
+
```markdown
|
|
264
|
+
# Agent Pattern Verification Report
|
|
265
|
+
|
|
266
|
+
**Project:** [project name or path]
|
|
267
|
+
**Date:** [current date]
|
|
268
|
+
**Framework:** [LangGraph | CrewAI | AutoGen | LangChain | Custom | None]
|
|
269
|
+
**Files analyzed:** [count]
|
|
270
|
+
|
|
271
|
+
## Summary
|
|
272
|
+
|
|
273
|
+
✅ X checks passed | ⚠️ Y warnings | ❌ Z issues
|
|
274
|
+
|
|
275
|
+
### By Category
|
|
276
|
+
|
|
277
|
+
| Category | Pass | Warn | Issue |
|
|
278
|
+
|----------|------|------|-------|
|
|
279
|
+
| Loop Safety | X | X | X |
|
|
280
|
+
| Retry Limits | X | X | X |
|
|
281
|
+
| Tool Consistency | X | X | X |
|
|
282
|
+
| Context Size | X | X | X |
|
|
283
|
+
| Graph Cycles | X | X | X |
|
|
284
|
+
|
|
285
|
+
## Detailed Findings
|
|
286
|
+
|
|
287
|
+
> `[P]` = pattern-matched (structurally reliable) · `[H]` = heuristic (best-effort judgment)
|
|
288
|
+
|
|
289
|
+
### ✅ Passing
|
|
290
|
+
|
|
291
|
+
- `[P]` All retry decorators have stop conditions
|
|
292
|
+
- `[P]` Tool registry consistent with prompt references
|
|
293
|
+
|
|
294
|
+
### ⚠️ Warnings
|
|
295
|
+
|
|
296
|
+
- `[P|H]` [Check name]: [Description]
|
|
297
|
+
- **Location:** [file:line]
|
|
298
|
+
- **Category:** [Loop Safety | Retry Limits | Tool Consistency | Context Size]
|
|
299
|
+
- **Suggestion:** [How to address]
|
|
300
|
+
|
|
301
|
+
### ❌ Issues
|
|
302
|
+
|
|
303
|
+
- `[P|H]` [Check name]: [Description]
|
|
304
|
+
- **Location:** [file:line]
|
|
305
|
+
- **Category:** [Loop Safety | Retry Limits | Tool Consistency | Context Size]
|
|
306
|
+
- **Rule:** [Which rule this violates]
|
|
307
|
+
- **Fix:** [Specific remediation steps]
|
|
308
|
+
|
|
309
|
+
## Recommendations
|
|
310
|
+
|
|
311
|
+
1. **[Highest priority]** - [Specific action]
|
|
312
|
+
2. **[Second priority]** - [Specific action]
|
|
313
|
+
3. [Additional improvements]
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
*Report generated by ControlKeel Agent Pattern Verification v1.0*
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Integration with CK Tools
|
|
321
|
+
|
|
322
|
+
### Using `ck_validate`
|
|
323
|
+
|
|
324
|
+
For pattern-matched checks that can be expressed as code patterns, use `ck_validate` with:
|
|
325
|
+
- `artifact_type: "source"`
|
|
326
|
+
- `intended_use: "code"`
|
|
327
|
+
- `domain_pack: "software"` or relevant domain
|
|
328
|
+
- `security_workflow_phase: "analysis"`
|
|
329
|
+
|
|
330
|
+
### Using `ck_finding`
|
|
331
|
+
|
|
332
|
+
Persist each issue with structured metadata:
|
|
333
|
+
```elixir
|
|
334
|
+
ck_finding(
|
|
335
|
+
category: "security",
|
|
336
|
+
finding_family: "agent_pattern",
|
|
337
|
+
affected_component: "agent/loop.py:45",
|
|
338
|
+
severity: "warning", # or "issue"
|
|
339
|
+
evidence_type: "code_pattern",
|
|
340
|
+
description: "Potential unbounded loop detected",
|
|
341
|
+
suggested_fix: "Add MAX_ITERATIONS constant or break condition",
|
|
342
|
+
check_type: "pattern" # or "heuristic"
|
|
343
|
+
)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Using `ck_context`
|
|
347
|
+
|
|
348
|
+
Call at the start to:
|
|
349
|
+
- Load existing findings to avoid duplicates
|
|
350
|
+
- Understand the risk tier and compliance profile
|
|
351
|
+
- Get workspace context for file discovery
|
|
352
|
+
|
|
353
|
+
## Additional Resources
|
|
354
|
+
|
|
355
|
+
For detailed check specifications and examples, see [references/pattern-checklist.md](references/pattern-checklist.md).
|