Skip to content

Commit 7af9629

Browse files
SilkWebclaude
andcommitted
Add agent proxy router, OpenAPI spec, Custom GPT config, and prompt page
- FastAPI proxy: routes /agents/{name}/* to correct agent port - OpenAPI 3.1 spec with 34 endpoints for ChatGPT Custom GPT Actions - Custom GPT instructions ready for GPT Builder - silkweb.io/prompt page with copy-to-clipboard universal prompt - httpx dependency for async proxy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6d50240 commit 7af9629

5 files changed

Lines changed: 2167 additions & 1 deletion

File tree

api/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from api.config import settings
2222
from api.middleware.rate_limit import RateLimitMiddleware
2323
from api.middleware.security import SecurityHeadersMiddleware
24-
from api.routers import agents, discovery, health, receipts, tasks
24+
from api.routers import agents, agents_proxy, discovery, health, receipts, tasks
2525

2626
# Logging
2727
logging.basicConfig(
@@ -93,6 +93,7 @@ def create_app() -> FastAPI:
9393
app.include_router(discovery.router)
9494
app.include_router(tasks.router)
9595
app.include_router(receipts.router)
96+
app.include_router(agents_proxy.router)
9697

9798
return app
9899

api/routers/agents_proxy.py

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
"""SilkWeb Agent Proxy Router.
2+
3+
Proxies requests from api.silkweb.io/agents/{agent_name}/{path}
4+
to the correct localhost port where each agent runs.
5+
6+
Agent port mapping:
7+
aegis -> 3003 (Cybersecurity)
8+
navigator -> 3004 (Logistics)
9+
sentinel -> 3005 (IT Ops)
10+
oracle -> 3006 (Finance)
11+
atlas -> 3007 (Geospatial)
12+
justice -> 3008 (Legal)
13+
shield -> 3009 (Personal Injury)
14+
fortress -> 3010 (Criminal Defense)
15+
design -> 3002 (Design)
16+
"""
17+
18+
import logging
19+
from typing import Any
20+
21+
import httpx
22+
from fastapi import APIRouter, Request
23+
from fastapi.responses import JSONResponse
24+
25+
logger = logging.getLogger("silkweb.agents_proxy")
26+
27+
router = APIRouter(prefix="/agents", tags=["agents-proxy"])
28+
29+
# ── Agent name -> localhost port mapping ──────────────────────────
30+
31+
AGENT_PORTS: dict[str, int] = {
32+
"aegis": 3003,
33+
"navigator": 3004,
34+
"sentinel": 3005,
35+
"oracle": 3006,
36+
"atlas": 3007,
37+
"justice": 3008,
38+
"shield": 3009,
39+
"fortress": 3010,
40+
"design": 3002,
41+
}
42+
43+
AGENT_METADATA: dict[str, dict[str, str]] = {
44+
"aegis": {
45+
"id": "aegis-security",
46+
"name": "AEGIS",
47+
"description": "Cybersecurity Threat Intelligence — URL scanning, SSL inspection, domain reputation, email security",
48+
},
49+
"navigator": {
50+
"id": "navigator-logistics",
51+
"name": "NAVIGATOR",
52+
"description": "Global Logistics Intelligence — route calculation, multimodal optimization, customs compliance, carbon footprint",
53+
},
54+
"sentinel": {
55+
"id": "sentinel-ops",
56+
"name": "SENTINEL",
57+
"description": "IT Infrastructure Monitoring — health checks, DNS resolution, SSL expiry, log analysis, incident classification",
58+
},
59+
"oracle": {
60+
"id": "oracle-finance",
61+
"name": "ORACLE",
62+
"description": "Financial Intelligence — company analysis, risk scoring, Benford's Law fraud detection, regulatory compliance",
63+
},
64+
"atlas": {
65+
"id": "atlas-geospatial",
66+
"name": "ATLAS",
67+
"description": "Geospatial Intelligence — distance calculations, geofencing, sun position, route analysis",
68+
},
69+
"justice": {
70+
"id": "justice-legal",
71+
"name": "JUSTICE",
72+
"description": "General Legal & Contract Law — contract analysis, NDA review, statute research, clause drafting, compliance",
73+
},
74+
"shield": {
75+
"id": "shield-injury",
76+
"name": "SHIELD",
77+
"description": "Personal Injury / Accident Law — case evaluation, damage calculation, statute of limitations, insurance analysis",
78+
},
79+
"fortress": {
80+
"id": "fortress-defense",
81+
"name": "FORTRESS",
82+
"description": "Criminal Defense Intelligence — charge analysis, constitutional rights, evidence suppression, sentencing guidelines",
83+
},
84+
"design": {
85+
"id": "sphinx-design",
86+
"name": "SPHINX",
87+
"description": "Design Intelligence Agent",
88+
},
89+
}
90+
91+
# Proxy timeout in seconds
92+
PROXY_TIMEOUT = 10.0
93+
94+
# Shared httpx async client (created lazily)
95+
_client: httpx.AsyncClient | None = None
96+
97+
98+
async def _get_client() -> httpx.AsyncClient:
99+
"""Get or create the shared httpx async client."""
100+
global _client
101+
if _client is None or _client.is_closed:
102+
_client = httpx.AsyncClient(
103+
timeout=httpx.Timeout(PROXY_TIMEOUT, connect=5.0),
104+
follow_redirects=False,
105+
limits=httpx.Limits(max_connections=50, max_keepalive_connections=10),
106+
)
107+
return _client
108+
109+
110+
# ── /agents/list — Agent directory ───────────────────────────────
111+
112+
@router.get("/list")
113+
async def list_agents() -> JSONResponse:
114+
"""Return a directory of all available agents with metadata."""
115+
agents = []
116+
client = await _get_client()
117+
118+
for name, port in AGENT_PORTS.items():
119+
meta = AGENT_METADATA.get(name, {})
120+
entry = {
121+
"id": meta.get("id", name),
122+
"name": meta.get("name", name.upper()),
123+
"description": meta.get("description", ""),
124+
"proxy_prefix": f"/agents/{name}",
125+
"status": "unknown",
126+
}
127+
128+
# Quick health check (non-blocking, with short timeout)
129+
try:
130+
resp = await client.get(
131+
f"http://127.0.0.1:{port}/health",
132+
timeout=httpx.Timeout(2.0),
133+
)
134+
if resp.status_code == 200:
135+
entry["status"] = "operational"
136+
else:
137+
entry["status"] = "degraded"
138+
except Exception:
139+
entry["status"] = "offline"
140+
141+
agents.append(entry)
142+
143+
return JSONResponse(
144+
content={"agents": agents, "count": len(agents)},
145+
headers=_cors_headers(),
146+
)
147+
148+
149+
# ── Catch-all proxy: /agents/{agent_name}/{path} ────────────────
150+
151+
@router.api_route(
152+
"/{agent_name}/{path:path}",
153+
methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
154+
)
155+
async def proxy_to_agent(agent_name: str, path: str, request: Request) -> JSONResponse:
156+
"""Proxy a request to the correct agent's localhost port.
157+
158+
Maps:
159+
POST /agents/aegis/scan/url -> POST http://127.0.0.1:3003/scan/url
160+
POST /agents/oracle/analyze/company -> POST http://127.0.0.1:3006/analyze/company
161+
"""
162+
# Handle CORS preflight
163+
if request.method == "OPTIONS":
164+
return JSONResponse(content={}, status_code=204, headers=_cors_headers())
165+
166+
# Resolve agent
167+
agent_key = agent_name.lower()
168+
port = AGENT_PORTS.get(agent_key)
169+
170+
if port is None:
171+
return JSONResponse(
172+
status_code=404,
173+
content={
174+
"error": f"Unknown agent: {agent_name}",
175+
"available_agents": list(AGENT_PORTS.keys()),
176+
},
177+
headers=_cors_headers(),
178+
)
179+
180+
# Build target URL
181+
target_url = f"http://127.0.0.1:{port}/{path}"
182+
183+
# Read request body (if any)
184+
body: bytes | None = None
185+
if request.method in ("POST", "PUT", "PATCH"):
186+
body = await request.body()
187+
188+
# Forward headers (only safe ones)
189+
forward_headers: dict[str, str] = {}
190+
content_type = request.headers.get("content-type")
191+
if content_type:
192+
forward_headers["Content-Type"] = content_type
193+
authorization = request.headers.get("authorization")
194+
if authorization:
195+
forward_headers["Authorization"] = authorization
196+
197+
# Proxy the request
198+
client = await _get_client()
199+
try:
200+
resp = await client.request(
201+
method=request.method,
202+
url=target_url,
203+
content=body,
204+
headers=forward_headers,
205+
)
206+
207+
# Try to return as JSON, fall back to plain text
208+
try:
209+
response_json = resp.json()
210+
return JSONResponse(
211+
content=response_json,
212+
status_code=resp.status_code,
213+
headers=_cors_headers(),
214+
)
215+
except Exception:
216+
return JSONResponse(
217+
content={"raw": resp.text},
218+
status_code=resp.status_code,
219+
headers=_cors_headers(),
220+
)
221+
222+
except httpx.TimeoutException:
223+
logger.warning(f"Timeout proxying to {agent_key} at {target_url}")
224+
return JSONResponse(
225+
status_code=504,
226+
content={
227+
"error": "Agent request timed out",
228+
"agent": agent_key,
229+
"timeout_seconds": PROXY_TIMEOUT,
230+
},
231+
headers=_cors_headers(),
232+
)
233+
except httpx.ConnectError:
234+
logger.warning(f"Connection refused for {agent_key} at {target_url}")
235+
return JSONResponse(
236+
status_code=502,
237+
content={
238+
"error": f"Agent '{agent_key}' is not running or unreachable",
239+
"agent": agent_key,
240+
"port": port,
241+
},
242+
headers=_cors_headers(),
243+
)
244+
except Exception as exc:
245+
logger.error(f"Proxy error for {agent_key}: {exc}")
246+
return JSONResponse(
247+
status_code=502,
248+
content={
249+
"error": "Proxy error",
250+
"agent": agent_key,
251+
"detail": str(exc),
252+
},
253+
headers=_cors_headers(),
254+
)
255+
256+
257+
# ── CORS helper ──────────────────────────────────────────────────
258+
259+
def _cors_headers() -> dict[str, str]:
260+
"""Return CORS headers that allow ChatGPT Custom GPT Actions."""
261+
return {
262+
"Access-Control-Allow-Origin": "*",
263+
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
264+
"Access-Control-Allow-Headers": "Authorization, Content-Type, openai-conversation-id, openai-ephemeral-user-id",
265+
"Access-Control-Max-Age": "3600",
266+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# SilkWeb Agents — Custom GPT Configuration
2+
3+
## GPT Name
4+
5+
SilkWeb Agents
6+
7+
## GPT Description (for Store listing)
8+
9+
Access 8 specialized AI agents for cybersecurity scanning, logistics routing, infrastructure monitoring, financial analysis, geospatial intelligence, contract law, personal injury evaluation, and criminal defense research. Real analytical tools, not just chat.
10+
11+
## System Prompt / Instructions
12+
13+
You are **SilkWeb Agents**, a gateway to a network of 8 specialized AI agents. Each agent has real analytical capabilities -- they perform actual computations, network requests, and data lookups rather than generating approximations.
14+
15+
### Available Agents
16+
17+
1. **AEGIS** (Cybersecurity) -- Scan URLs for security headers, inspect SSL certificates, analyze domain DNS/email authentication, check email security, and test password strength.
18+
2. **NAVIGATOR** (Logistics) -- Calculate shipping routes with haversine distance, compare transport modes (air/sea/rail/truck) for cost/time/CO2, check customs compliance between countries, and estimate carbon footprint.
19+
3. **SENTINEL** (IT Ops) -- Perform HTTP health checks on websites, resolve DNS across multiple public resolvers, monitor SSL certificate expiry, analyze log files for errors and patterns, and classify incidents with root cause suggestions.
20+
4. **ORACLE** (Finance) -- Analyze company financials with 20+ ratios and a health grade, assess partnership risk between two companies, detect fraud using Benford's Law and anomaly detection, and check regulatory compliance across 7 jurisdictions.
21+
5. **ATLAS** (Geospatial) -- Calculate precise distances using Vincenty/haversine formulas, test point-in-polygon geofences, look up elevation data, compute sunrise/sunset/twilight times, and analyze multi-waypoint routes.
22+
6. **JUSTICE** (Legal) -- Analyze contract text for risky clauses and missing protections, review NDAs for scope and enforceability, research statutes by legal topic, draft standard clause language from templates, and check business compliance requirements.
23+
7. **SHIELD** (Personal Injury) -- Evaluate case strength with settlement range estimates, calculate economic and non-economic damages, check statute of limitations deadlines by state, analyze insurance policy coverage gaps, and provide accident action guides.
24+
8. **FORTRESS** (Criminal Defense) -- Look up federal charges with elements and penalties, explain constitutional rights by situation, analyze evidence for suppression arguments, calculate sentencing guidelines, and compare charges for plea bargain strategy.
25+
26+
### How to Use the Agents
27+
28+
When a user asks a question, determine which agent(s) are relevant and call the appropriate action. You can call multiple agents in a single turn if the question spans domains.
29+
30+
**Always present the results in a clear, readable format.** Highlight key findings, scores, grades, and actionable recommendations. Use tables when comparing data.
31+
32+
**Important disclaimers:**
33+
- Legal agents (JUSTICE, SHIELD, FORTRESS) provide AI-generated legal **information**, not legal advice. Always remind users to consult a licensed attorney.
34+
- Financial analysis (ORACLE) is for informational purposes only, not investment advice.
35+
- Security scans (AEGIS, SENTINEL) provide a point-in-time assessment and should supplement, not replace, professional security audits.
36+
37+
### Response Guidelines
38+
39+
- Be direct and actionable. Lead with the most important findings.
40+
- When an agent returns a grade (A-F) or score, always mention it prominently.
41+
- For security scans, prioritize critical and high-severity findings.
42+
- For legal queries, always include the disclaimer about consulting an attorney.
43+
- For financial analysis, explain what the ratios mean in plain language.
44+
- For logistics, highlight the recommended option (fastest, cheapest, greenest).
45+
- If an agent returns an error (e.g., could not resolve a location), explain it clearly and suggest alternatives.
46+
47+
### Agent Selection Guide
48+
49+
| User Intent | Agent | Action |
50+
|---|---|---|
51+
| "Is this website secure?" | AEGIS | aegisFullReport or aegisScanUrl |
52+
| "Check SSL certificate" | AEGIS | aegisScanSsl |
53+
| "Is this email legit?" | AEGIS | aegisScanEmail |
54+
| "How strong is this password?" | AEGIS | aegisScanPassword |
55+
| "Ship from Shanghai to LA" | NAVIGATOR | navigatorRouteCalculate |
56+
| "Customs docs for US to China" | NAVIGATOR | navigatorComplianceCustoms |
57+
| "Carbon footprint of shipping" | NAVIGATOR | navigatorEstimateCarbon |
58+
| "Is example.com up?" | SENTINEL | sentinelMonitorHealth |
59+
| "Check DNS for my domain" | SENTINEL | sentinelMonitorDns |
60+
| "Analyze these server logs" | SENTINEL | sentinelAnalyzeLogs |
61+
| "Server is down, help!" | SENTINEL | sentinelAnalyzeIncident |
62+
| "Analyze this company's finances" | ORACLE | oracleAnalyzeCompany |
63+
| "Is this partnership risky?" | ORACLE | oracleAnalyzeRisk |
64+
| "Check these numbers for fraud" | ORACLE | oracleDetectFraud |
65+
| "What regulations apply to us?" | ORACLE | oracleComplianceCheck |
66+
| "Distance from Tokyo to London" | ATLAS | atlasGeoDistance |
67+
| "Is this point inside my zone?" | ATLAS | atlasGeoGeofence |
68+
| "Sunrise time in Paris" | ATLAS | atlasGeoSun |
69+
| "Review this contract" | JUSTICE | justiceAnalyzeContract |
70+
| "Analyze this NDA" | JUSTICE | justiceAnalyzeNda |
71+
| "What law covers breach of contract?" | JUSTICE | justiceResearchStatute |
72+
| "Draft an indemnification clause" | JUSTICE | justiceDraftClause |
73+
| "I was in a car accident" | SHIELD | shieldEvaluateCase |
74+
| "Calculate my injury damages" | SHIELD | shieldCalculateDamages |
75+
| "Has my statute of limitations expired?" | SHIELD | shieldCheckStatute |
76+
| "Analyze my auto insurance" | SHIELD | shieldAnalyzeInsurance |
77+
| "What should I do after a slip and fall?" | SHIELD | shieldGuideSteps |
78+
| "What is wire fraud?" | FORTRESS | fortressAnalyzeCharge |
79+
| "What are my rights during a traffic stop?" | FORTRESS | fortressRightsExplain |
80+
| "Can this evidence be suppressed?" | FORTRESS | fortressAnalyzeEvidence |
81+
| "What sentence for drug trafficking?" | FORTRESS | fortressSentencingGuide |
82+
| "Compare wire fraud vs mail fraud" | FORTRESS | fortressCompareCharges |
83+
84+
## Conversation Starters
85+
86+
- Run a full security scan on my website
87+
- Calculate the cheapest shipping route from Shanghai to Los Angeles
88+
- Analyze this contract for risky clauses
89+
- What are the penalties for wire fraud?
90+
- Check if my company needs to comply with GDPR
91+
- What are my rights if I get pulled over?
92+
- Calculate damages for my car accident injuries
93+
- How far is it from Tokyo to London?
94+
95+
## Configuration Notes
96+
97+
- **Authentication**: None required (public API, rate-limited)
98+
- **API Server**: `https://api.silkweb.io`
99+
- **OpenAPI Spec URL**: `https://silkweb.io/openapi.json`
100+
- **Privacy Policy**: `https://silkweb.io/privacy`

0 commit comments

Comments
 (0)