agentops-cockpit 0.5.0__py3-none-any.whl → 0.9.5__py3-none-any.whl
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.
- agent_ops_cockpit/agent.py +137 -0
- agent_ops_cockpit/cli/main.py +104 -11
- agent_ops_cockpit/eval/load_test.py +15 -10
- agent_ops_cockpit/eval/quality_climber.py +23 -5
- agent_ops_cockpit/eval/red_team.py +5 -4
- agent_ops_cockpit/mcp_server.py +55 -21
- agent_ops_cockpit/ops/arch_review.py +78 -17
- agent_ops_cockpit/ops/cost_optimizer.py +0 -1
- agent_ops_cockpit/ops/evidence_bridge.py +132 -0
- agent_ops_cockpit/ops/frameworks.py +79 -10
- agent_ops_cockpit/ops/mcp_hub.py +1 -2
- agent_ops_cockpit/ops/orchestrator.py +363 -49
- agent_ops_cockpit/ops/pii_scrubber.py +1 -1
- agent_ops_cockpit/ops/policies.json +26 -0
- agent_ops_cockpit/ops/policy_engine.py +85 -0
- agent_ops_cockpit/ops/reliability.py +30 -10
- agent_ops_cockpit/ops/secret_scanner.py +10 -3
- agent_ops_cockpit/ops/ui_auditor.py +52 -11
- agent_ops_cockpit/ops/watcher.py +138 -0
- agent_ops_cockpit/ops/watchlist.json +88 -0
- agent_ops_cockpit/optimizer.py +361 -53
- agent_ops_cockpit/shadow/router.py +7 -8
- agent_ops_cockpit/system_prompt.md +13 -0
- agent_ops_cockpit/tests/golden_set.json +52 -0
- agent_ops_cockpit/tests/test_agent.py +34 -0
- agent_ops_cockpit/tests/test_arch_review.py +45 -0
- agent_ops_cockpit/tests/test_frameworks.py +100 -0
- agent_ops_cockpit/tests/test_optimizer.py +68 -0
- agent_ops_cockpit/tests/test_quality_climber.py +18 -0
- agent_ops_cockpit/tests/test_red_team.py +35 -0
- agent_ops_cockpit/tests/test_secret_scanner.py +24 -0
- agentops_cockpit-0.9.5.dist-info/METADATA +246 -0
- agentops_cockpit-0.9.5.dist-info/RECORD +47 -0
- {agentops_cockpit-0.5.0.dist-info → agentops_cockpit-0.9.5.dist-info}/entry_points.txt +1 -1
- agentops_cockpit-0.5.0.dist-info/METADATA +0 -171
- agentops_cockpit-0.5.0.dist-info/RECORD +0 -32
- {agentops_cockpit-0.5.0.dist-info → agentops_cockpit-0.9.5.dist-info}/WHEEL +0 -0
- {agentops_cockpit-0.5.0.dist-info → agentops_cockpit-0.9.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
3
4
|
from rich.console import Console
|
|
4
5
|
from rich.table import Table
|
|
5
6
|
from rich.panel import Panel
|
|
6
7
|
|
|
8
|
+
from agent_ops_cockpit.ops.frameworks import detect_framework, FRAMEWORKS
|
|
9
|
+
|
|
7
10
|
app = typer.Typer(help="Agent Architecture Reviewer: Audit your design against Google Well-Architected Framework.")
|
|
8
11
|
console = Console()
|
|
9
12
|
|
|
10
|
-
from agent_ops_cockpit.ops.frameworks import detect_framework, FRAMEWORKS
|
|
11
|
-
|
|
12
13
|
@app.command()
|
|
13
14
|
def audit(path: str = "."):
|
|
14
15
|
"""
|
|
@@ -18,15 +19,11 @@ def audit(path: str = "."):
|
|
|
18
19
|
framework_data = FRAMEWORKS[framework_key]
|
|
19
20
|
checklist = framework_data["checklist"]
|
|
20
21
|
framework_name = framework_data["name"]
|
|
21
|
-
|
|
22
|
-
console.print(Panel.fit(f"🏛️ [bold blue]{framework_name.upper()}: ARCHITECTURE REVIEW[/bold blue]", border_style="blue"))
|
|
23
|
-
console.print(f"Detected Framework: [bold green]{framework_name}[/bold green]")
|
|
24
|
-
console.print(f"Comparing local agent implementation against [bold]{framework_name} Best Practices[/bold]...\n")
|
|
25
|
-
|
|
26
22
|
# Read all relevant code files for inspection
|
|
27
23
|
code_content = ""
|
|
28
24
|
for root, dirs, files in os.walk(path):
|
|
29
|
-
if any(d in root for d in [".venv", "node_modules", ".git"]):
|
|
25
|
+
if any(d in root for d in [".venv", "node_modules", ".git"]):
|
|
26
|
+
continue
|
|
30
27
|
for file in files:
|
|
31
28
|
if file.endswith((".py", ".ts", ".tsx", ".js")):
|
|
32
29
|
try:
|
|
@@ -35,8 +32,34 @@ def audit(path: str = "."):
|
|
|
35
32
|
except Exception:
|
|
36
33
|
pass
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if framework_key == "generic":
|
|
36
|
+
console.print(Panel.fit("🔍 [bold yellow]SHADOW INTELLIGENCE: ZERO-SHOT AUDIT INITIALIZED[/bold yellow]", border_style="yellow"))
|
|
37
|
+
console.print("⚠️ [dim]Detected Unknown Technology Stack. Switching to Structural Pattern Matching...[/dim]")
|
|
38
|
+
|
|
39
|
+
# Self-Learning Heuristic: Look for patterns even if tech is unknown
|
|
40
|
+
structural_indicators = {
|
|
41
|
+
"decorators": r"@[\w\.]+",
|
|
42
|
+
"async_loops": r"async\s+def.*await",
|
|
43
|
+
"class_hierarchy": r"class\s+\w+\(\w*\):",
|
|
44
|
+
"environment_vars": r"os\.environ|process\.env",
|
|
45
|
+
"structured_output": r"Pydantic|BaseModel|zod|interface",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
found_patterns = []
|
|
49
|
+
for p_name, pattern in structural_indicators.items():
|
|
50
|
+
if re.search(pattern, code_content):
|
|
51
|
+
found_patterns.append(p_name)
|
|
52
|
+
|
|
53
|
+
if found_patterns:
|
|
54
|
+
console.print(f"📡 [bold green]Heuristically identified patterns:[/bold green] {', '.join(found_patterns)}")
|
|
55
|
+
console.print("Adjusting audit benchmarks for custom agentic architecture...\n")
|
|
56
|
+
|
|
57
|
+
console.print(Panel.fit(f"🏛️ [bold blue]{framework_name.upper()}: ARCHITECTURE REVIEW[/bold blue]", border_style="blue"))
|
|
58
|
+
console.print(f"Detected Framework: [bold green]{framework_name}[/bold green]")
|
|
59
|
+
console.print(f"Comparing local agent implementation against [bold]{framework_name} Best Practices[/bold]...\n")
|
|
60
|
+
|
|
61
|
+
total_checks = 0.0
|
|
62
|
+
passed_checks = 0.0
|
|
40
63
|
current_check_num = 0
|
|
41
64
|
|
|
42
65
|
with console.status("[bold blue]Scanning architecture...") as status:
|
|
@@ -49,7 +72,7 @@ def audit(path: str = "."):
|
|
|
49
72
|
for check_text, rationale in section["checks"]:
|
|
50
73
|
current_check_num += 1
|
|
51
74
|
check_key = check_text.split(":")[0].strip()
|
|
52
|
-
status.update(f"[bold blue]
|
|
75
|
+
status.update(f"[bold blue]Step {current_check_num}: Checking {check_key}...")
|
|
53
76
|
|
|
54
77
|
# Simple heuristic audit: check if certain keywords exist in the code
|
|
55
78
|
keywords = {
|
|
@@ -59,7 +82,7 @@ def audit(path: str = "."):
|
|
|
59
82
|
"Identity": ["iam", "auth", "token", "oauth", "workloadidentity"],
|
|
60
83
|
"Moderation": ["moderate", "safety", "filter"],
|
|
61
84
|
"Routing": ["router", "switch", "map", "agentengine"],
|
|
62
|
-
"Outputs": ["schema", "json", "structured"],
|
|
85
|
+
"Outputs": ["schema", "json", "structured", "basemodel", "interface"],
|
|
63
86
|
"HITL": ["approve", "confirm", "human"],
|
|
64
87
|
"Confirmation": ["confirm", "ask", "approve"],
|
|
65
88
|
"Logging": ["log", "trace", "audit", "reasoningengine"],
|
|
@@ -69,9 +92,39 @@ def audit(path: str = "."):
|
|
|
69
92
|
"A2UI": ["a2ui", "renderer", "registry", "component"],
|
|
70
93
|
"Responsive": ["@media", "max-width", "flex", "grid", "vw", "vh"],
|
|
71
94
|
"Accessibility": ["aria-", "role=", "alt=", "tabindex"],
|
|
72
|
-
"
|
|
95
|
+
"Policies": ["policies.json", "policy_engine", "forbidden_topics", "hitl"],
|
|
96
|
+
"Triggers": ["trigger", "callback", "handle", "onclick"],
|
|
97
|
+
"Resiliency": ["retry", "tenacity", "backoff", "exponential"],
|
|
98
|
+
"Prompts": [".md", ".yaml", ".prompt", "load_prompt", "jinja2"],
|
|
99
|
+
"Sessions": ["session", "state", "conversation_id", "thread_id"],
|
|
100
|
+
"Retrieval": ["rag", "vector", "embedding", "context_cache", "retrieval", "pinecone", "alloydb", "cloudsql", "bigquery", "firestore", "spanner", "redshift", "snowflake", "databricks", "s3", "blob"],
|
|
101
|
+
"Reasoning": ["while", "for", "loop", "invoke", "call", "run", "execute", "chain", "agent"],
|
|
102
|
+
"State": ["memory", "state", "db", "redis", "history", "session", "storage"],
|
|
103
|
+
"Tools": ["tool", "registry", "dispatcher", "handler", "mcp", "api", "sdk", "client", "connect"],
|
|
104
|
+
"Safety": ["filter", "clean", "sanitize", "scrub", "guard"],
|
|
105
|
+
"Shadow Mode": ["shadow", "router", "dual_rollout", "traffic_split", "version_v2"],
|
|
106
|
+
"Orchestration": ["swarm", "coordinator", "manager_agent", "supervisor", "orchestrator", "worker_agent"],
|
|
107
|
+
"VPC": ["vpc_sc", "service_control", "isolated_network", "private_endpoint"],
|
|
108
|
+
"Observability": ["otel", "trace", "span", "telemetry", "opentelemetry", "cloud_trace"],
|
|
109
|
+
"Governance": ["policies.json", "hitl", "approval", "policy_engine"],
|
|
110
|
+
"Legal": ["copyright", "license", "disclaimer", "data_residency", "privacy", "tos", "terms_of_service"],
|
|
111
|
+
"Marketing": ["brand", "tone", "vibrant", "consistent", "seo", "og:image", "description", "cta"]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Weighting: Security and Core Architecture are more important
|
|
115
|
+
weights = {
|
|
116
|
+
"🏗️": 1.5,
|
|
117
|
+
"🛡️": 2.0,
|
|
118
|
+
"🎭": 1.0,
|
|
119
|
+
"🧗": 1.2,
|
|
120
|
+
"📉": 1.3,
|
|
121
|
+
"⚖️": 1.8, # Legal/Compliance
|
|
122
|
+
"📢": 0.9 # Marketing/Brand
|
|
73
123
|
}
|
|
74
124
|
|
|
125
|
+
category_prefix = section["category"][:2]
|
|
126
|
+
weight = weights.get(category_prefix, 1.0)
|
|
127
|
+
|
|
75
128
|
# If any keyword for this check type is found, mark as PASSED
|
|
76
129
|
matched = False
|
|
77
130
|
for k, words in keywords.items():
|
|
@@ -82,12 +135,18 @@ def audit(path: str = "."):
|
|
|
82
135
|
|
|
83
136
|
if matched:
|
|
84
137
|
check_status = "[bold green]PASSED[/bold green]"
|
|
85
|
-
passed_checks +=
|
|
138
|
+
passed_checks += weight
|
|
139
|
+
# Output source for evidence bridge
|
|
140
|
+
if "Google" in framework_name:
|
|
141
|
+
console.print(f"SOURCE: {check_key} | https://cloud.google.com/architecture/framework | Google Cloud Architecture Framework: {section['category']}")
|
|
86
142
|
else:
|
|
87
143
|
check_status = "[bold red]FAIL[/bold red]"
|
|
144
|
+
# Output action for report
|
|
145
|
+
console.print(f"ACTION: codebase | Architecture Gap: {check_key} | {rationale}")
|
|
146
|
+
if "Google" in framework_name:
|
|
147
|
+
console.print(f"SOURCE: {check_key} | https://cloud.google.com/architecture/framework | Recommended Pattern: {check_text}")
|
|
88
148
|
|
|
89
|
-
|
|
90
|
-
time.sleep(0.1) # Simulate deep heuristic scan
|
|
149
|
+
total_checks += weight
|
|
91
150
|
|
|
92
151
|
table.add_row(check_text, check_status, rationale)
|
|
93
152
|
|
|
@@ -97,8 +156,10 @@ def audit(path: str = "."):
|
|
|
97
156
|
score = (passed_checks / total_checks) * 100 if total_checks > 0 else 0
|
|
98
157
|
console.print(f"📊 [bold]Review Score: {score:.0f}/100[/bold]")
|
|
99
158
|
if score >= 80:
|
|
100
|
-
console.print(
|
|
159
|
+
console.print("✅ [bold green]Architecture Review Complete.[/bold green] Your agent is well-aligned with optimized patterns.")
|
|
101
160
|
else:
|
|
161
|
+
if framework_key == "generic":
|
|
162
|
+
console.print("💡 [bold yellow]Self-Learning Note:[/bold yellow] Found unknown tech. I have mapped your code structure to universal agentic pillars (Reasoning/Tools/Safety).")
|
|
102
163
|
console.print("⚠️ [bold yellow]Review Complete with warnings.[/bold yellow] Your agent has gaps in best practices. See results above.")
|
|
103
164
|
|
|
104
165
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import urllib.request
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
import re
|
|
6
|
+
from typing import Dict, Any, Optional, List
|
|
7
|
+
import importlib.metadata
|
|
8
|
+
from packaging import version
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
WATCHLIST_PATH = os.path.join(os.path.dirname(__file__), "watchlist.json")
|
|
14
|
+
|
|
15
|
+
def clean_version(v_str: str) -> str:
|
|
16
|
+
match = re.search(r'(\d+\.\d+(?:\.\d+)?(?:[a-zA-Z]+\d+)?)', v_str)
|
|
17
|
+
if match:
|
|
18
|
+
return match.group(1)
|
|
19
|
+
return v_str.strip().lstrip('v')
|
|
20
|
+
|
|
21
|
+
def fetch_latest_from_atom(url: str) -> Optional[Dict[str, str]]:
|
|
22
|
+
try:
|
|
23
|
+
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
|
24
|
+
with urllib.request.urlopen(req, timeout=10) as response:
|
|
25
|
+
tree = ET.parse(response)
|
|
26
|
+
root = tree.getroot()
|
|
27
|
+
ns = {'ns': 'http://www.w3.org/2005/Atom'}
|
|
28
|
+
|
|
29
|
+
latest_entry = root.find('ns:entry', ns)
|
|
30
|
+
if latest_entry is not None:
|
|
31
|
+
title = latest_entry.find('ns:title', ns).text
|
|
32
|
+
updated = latest_entry.find('ns:updated', ns).text
|
|
33
|
+
content_node = latest_entry.find('ns:content', ns)
|
|
34
|
+
summary = ""
|
|
35
|
+
if content_node is not None:
|
|
36
|
+
summary = re.sub('<[^<]+?>', '', content_node.text or "")[:500] + "..."
|
|
37
|
+
|
|
38
|
+
raw_v = title.strip().split()[-1]
|
|
39
|
+
return {
|
|
40
|
+
"version": clean_version(raw_v) if "==" not in raw_v else clean_version(raw_v.split("==")[-1]),
|
|
41
|
+
"date": updated,
|
|
42
|
+
"title": title,
|
|
43
|
+
"summary": summary
|
|
44
|
+
}
|
|
45
|
+
except Exception:
|
|
46
|
+
return None
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def get_installed_version(package_name: str) -> str:
|
|
50
|
+
try:
|
|
51
|
+
return importlib.metadata.version(package_name)
|
|
52
|
+
except importlib.metadata.PackageNotFoundError:
|
|
53
|
+
return "Not Installed"
|
|
54
|
+
|
|
55
|
+
def get_package_evidence(package_name: str) -> Dict[str, Any]:
|
|
56
|
+
if not os.path.exists(WATCHLIST_PATH):
|
|
57
|
+
return {"error": "Watchlist not found"}
|
|
58
|
+
|
|
59
|
+
with open(WATCHLIST_PATH, 'r') as f:
|
|
60
|
+
watchlist = json.load(f)
|
|
61
|
+
|
|
62
|
+
# Flatten categories to find the package
|
|
63
|
+
for cat_name, cat in watchlist.items():
|
|
64
|
+
if cat_name == "compatibility_rules":
|
|
65
|
+
continue
|
|
66
|
+
for name, info in cat.items():
|
|
67
|
+
if info.get("package") == package_name or name == package_name:
|
|
68
|
+
latest = fetch_latest_from_atom(info["feed"])
|
|
69
|
+
installed = get_installed_version(package_name)
|
|
70
|
+
min_v = info.get("min_version_for_optimizations", "0.0.0")
|
|
71
|
+
|
|
72
|
+
upgrade_required = False
|
|
73
|
+
if installed != "Not Installed":
|
|
74
|
+
try:
|
|
75
|
+
if version.parse(installed) < version.parse(min_v):
|
|
76
|
+
upgrade_required = True
|
|
77
|
+
except Exception:
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
"package": package_name,
|
|
82
|
+
"installed_version": installed,
|
|
83
|
+
"latest_version": latest["version"] if latest else "Unknown",
|
|
84
|
+
"min_optimized_version": min_v,
|
|
85
|
+
"upgrade_required": upgrade_required,
|
|
86
|
+
"release_date": latest["date"] if latest else "Unknown",
|
|
87
|
+
"source_url": info["feed"].replace(".atom", ""),
|
|
88
|
+
"best_practice_context": latest["summary"] if latest else "Check release notes for performance/security enhancements."
|
|
89
|
+
}
|
|
90
|
+
return {"error": f"Package {package_name} not found in watchlist"}
|
|
91
|
+
|
|
92
|
+
def get_compatibility_report(installed_packages: List[str]) -> List[Dict[str, Any]]:
|
|
93
|
+
if not os.path.exists(WATCHLIST_PATH):
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
with open(WATCHLIST_PATH, 'r') as f:
|
|
97
|
+
watchlist = json.load(f)
|
|
98
|
+
|
|
99
|
+
rules = watchlist.get("compatibility_rules", [])
|
|
100
|
+
reports = []
|
|
101
|
+
|
|
102
|
+
# Normalize imports to find root package names
|
|
103
|
+
roots = set()
|
|
104
|
+
for pkg in installed_packages:
|
|
105
|
+
roots.add(pkg.split('.')[0].replace('-', '_'))
|
|
106
|
+
|
|
107
|
+
for rule in rules:
|
|
108
|
+
comp_root = rule["component"].replace('-', '_')
|
|
109
|
+
if comp_root in roots:
|
|
110
|
+
# Check for incompatibilities
|
|
111
|
+
for forbidden in rule.get("incompatible_with", []):
|
|
112
|
+
forbidden_root = forbidden.replace('-', '_')
|
|
113
|
+
if forbidden_root in roots:
|
|
114
|
+
reports.append({
|
|
115
|
+
"type": "INCOMPATIBLE",
|
|
116
|
+
"component": rule["component"],
|
|
117
|
+
"conflict_with": forbidden,
|
|
118
|
+
"reason": rule["reason"]
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
# Check for synergies
|
|
122
|
+
for synergy in rule.get("works_well_with", []):
|
|
123
|
+
synergy_root = synergy.replace('-', '_')
|
|
124
|
+
if synergy_root in roots:
|
|
125
|
+
reports.append({
|
|
126
|
+
"type": "SYNERGY",
|
|
127
|
+
"component": rule["component"],
|
|
128
|
+
"partner": synergy,
|
|
129
|
+
"reason": f"Optimally paired with ecosystem partner {synergy}."
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
return reports
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
-
from typing import Dict, List, Any
|
|
4
3
|
|
|
5
4
|
# --- CHECKLISTS ---
|
|
6
5
|
|
|
@@ -11,7 +10,8 @@ GOOGLE_CHECKLIST = [
|
|
|
11
10
|
("Runtime: Is the agent running on Cloud Run or GKE?", "Critical for scalability and cost."),
|
|
12
11
|
("Framework: Is ADK used for tool orchestration?", "Google-standard for agent-tool communication."),
|
|
13
12
|
("Sandbox: Is Code Execution running in Vertex AI Sandbox?", "Prevents malicious code execution."),
|
|
14
|
-
("Backend: Is FastAPI used for the Engine layer?", "Industry-standard for high-concurrency agent apps.")
|
|
13
|
+
("Backend: Is FastAPI used for the Engine layer?", "Industry-standard for high-concurrency agent apps."),
|
|
14
|
+
("Outputs: Are Pydantic or Response Schemas used for structured output?", "Ensures data integrity and reliable tool execution.")
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -19,7 +19,8 @@ GOOGLE_CHECKLIST = [
|
|
|
19
19
|
"checks": [
|
|
20
20
|
("PII: Is a scrubber active before sending data to LLM?", "Compliance requirement (GDPR/SOC2)."),
|
|
21
21
|
("Identity: Is IAM used for tool access?", "Ensures least-privilege security."),
|
|
22
|
-
("Safety: Are Vertex AI Safety Filters configured?", "Protects against toxic generation.")
|
|
22
|
+
("Safety: Are Vertex AI Safety Filters configured?", "Protects against toxic generation."),
|
|
23
|
+
("Policies: Is 'policies.json' used for declarative guardrails?", "Enforces RFC-307 standards for forbidden topics and tool HITL.")
|
|
23
24
|
]
|
|
24
25
|
},
|
|
25
26
|
{
|
|
@@ -47,6 +48,33 @@ GOOGLE_CHECKLIST = [
|
|
|
47
48
|
("Accessibility: Do interactive elements have aria-labels?", "Critical for inclusive design and automated testing."),
|
|
48
49
|
("Triggers: Are you using interactive triggers for state changes?", "Improves 'Agentic Feel' through reactive UI.")
|
|
49
50
|
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"category": "🧗 Resiliency & Best Practices",
|
|
54
|
+
"checks": [
|
|
55
|
+
("Resiliency: Are retries with exponential backoff used for API/DB calls?", "Prevents cascading failures during downtime (e.g., using tenacity)."),
|
|
56
|
+
("Prompts: Are prompts stored in external '.md' or '.yaml' files?", "Best practice for separation of concerns and versioning."),
|
|
57
|
+
("Sessions: Is there a session/conversation management layer?", "Ensures context continuity and user state tracking."),
|
|
58
|
+
("Retrieval: Are you using RAG or Efficient Context Caching for large datasets?", "Optimizes performance vs. cost for retrieval-heavy agents.")
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"category": "⚖️ Legal & Compliance",
|
|
63
|
+
"checks": [
|
|
64
|
+
("Copyright: Does every source file have a legal copyright header?", "IP protection and enterprise policy."),
|
|
65
|
+
("License: Is there a LICENSE file in the root?", "Mandatory for legal distribution."),
|
|
66
|
+
("Disclaimer: Does the agent provide a clear LLM-usage disclaimer?", "Liability mitigation for AI hallucinations."),
|
|
67
|
+
("Data Residency: Is the agent region-restricted to us-central1 or equivalent?", "Ensures data stays within geofenced boundaries.")
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"category": "📢 Marketing & Brand",
|
|
72
|
+
"checks": [
|
|
73
|
+
("Tone: Is the system prompt aligned with brand voice (Helpful/Professional)?", "Consistency in agent personality."),
|
|
74
|
+
("SEO: Are OpenGraph and meta-tags present in the Face layer?", "Critical for discoverability and social sharing."),
|
|
75
|
+
("Vibrancy: Does the UI use the standard corporate color palette?", "Prevents ad-hoc branding in autonomous UIs."),
|
|
76
|
+
("CTA: Is there a clear Call-to-Action for every agent proposing a tool?", "Drives conversion and user engagement.")
|
|
77
|
+
]
|
|
50
78
|
}
|
|
51
79
|
]
|
|
52
80
|
|
|
@@ -214,18 +242,49 @@ LANGCHAIN_CHECKLIST = [
|
|
|
214
242
|
|
|
215
243
|
GENERIC_CHECKLIST = [
|
|
216
244
|
{
|
|
217
|
-
"category": "🏗️
|
|
245
|
+
"category": "🏗️ Zero-Shot Discovery (Unknown Tech)",
|
|
246
|
+
"checks": [
|
|
247
|
+
("Reasoning: Does the code exhibit a core reasoning/execution loop?", "Detected Structural Pattern: Universal Agentic Loop."),
|
|
248
|
+
("State: Is there an identifiable state management or memory pattern?", "Ensures session continuity even in custom stacks."),
|
|
249
|
+
("Tools: Are external functions being called via a registry or dispatcher?", "Standard for tool-enabled agents."),
|
|
250
|
+
("Safety: Are there any input/output sanitization blocks?", "Basic security hygiene for any AI application.")
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
ORACLE_CHECKLIST = [
|
|
256
|
+
{
|
|
257
|
+
"category": "🏗️ Oracle Cloud Architecture",
|
|
218
258
|
"checks": [
|
|
219
|
-
("
|
|
220
|
-
("
|
|
221
|
-
("
|
|
259
|
+
("Platform: Using OCI Generative AI or AI Agents?", "OCI-native managed agent orchestration."),
|
|
260
|
+
("Data: Is Oracle Database 23ai (Vector Search) used?", "Enterprise-grade vector grounding for RAG."),
|
|
261
|
+
("Compute: Is the agent running on OCI Container Instances or OCI Functions?", "Scale-to-zero and high-performance OCI compute options.")
|
|
222
262
|
]
|
|
223
263
|
},
|
|
224
264
|
{
|
|
225
|
-
"category": "🛡️ Security",
|
|
265
|
+
"category": "🛡️ Security & Governance (Oracle)",
|
|
226
266
|
"checks": [
|
|
227
|
-
("
|
|
228
|
-
("
|
|
267
|
+
("Identity: Is OCI IAM with dynamic groups enabled?", "Ensures secure, credential-less access to OCI resources."),
|
|
268
|
+
("Secrets: Using OCI Vault for API/DB secrets?", "Production standard for key management on OCI."),
|
|
269
|
+
("Network: Is the agent isolated in an OCI VCN with Private Endpoints?", "Prevents internet exposure of internal agent tools.")
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
CREWAI_CHECKLIST = [
|
|
275
|
+
{
|
|
276
|
+
"category": "🏗️ CrewAI Multi-Agent Architecture",
|
|
277
|
+
"checks": [
|
|
278
|
+
("Orchestration: Is the 'Process' defined (Sequential/Hierarchical)?", "CrewAI best practice for complex team coordination."),
|
|
279
|
+
("Memory: Is Short-term or Long-term memory enabled?", "Critical for maintaining context across multi-agent tasks."),
|
|
280
|
+
("Tools: Are tools shared across the Crew or specific to Agents?", "Promotes agent specialization and efficiency.")
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"category": "🛡️ Security & Reliability",
|
|
285
|
+
"checks": [
|
|
286
|
+
("Manager: Is a 'Manager Agent' used for hierarchical crews?", "Provides a central governance layer for agent handoffs."),
|
|
287
|
+
("Delegation: Is 'allow_delegation' configured per agent?", "Controls the communication flow between autonomous agents.")
|
|
229
288
|
]
|
|
230
289
|
}
|
|
231
290
|
]
|
|
@@ -370,6 +429,16 @@ FRAMEWORKS = {
|
|
|
370
429
|
"checklist": FIREBASE_CHECKLIST,
|
|
371
430
|
"indicators": [r"firebase\.json", r"\.firebaserc", r"firestore"]
|
|
372
431
|
},
|
|
432
|
+
"oracle": {
|
|
433
|
+
"name": "Oracle Cloud Infrastructure (OCI)",
|
|
434
|
+
"checklist": ORACLE_CHECKLIST,
|
|
435
|
+
"indicators": [r"oci", r"oracle", r"23ai"]
|
|
436
|
+
},
|
|
437
|
+
"crewai": {
|
|
438
|
+
"name": "CrewAI",
|
|
439
|
+
"checklist": CREWAI_CHECKLIST,
|
|
440
|
+
"indicators": [r"crewai", r"Agent\(", r"Task\(", r"Crew\("]
|
|
441
|
+
},
|
|
373
442
|
"generic": {
|
|
374
443
|
|
|
375
444
|
"name": "Generic Agentic Stack",
|