API Reference¶
All API endpoints are served by oktsec serve on the configured port (default: 8080).
Message API¶
POST /v1/message¶
Send a message through the security pipeline.
Request:
curl -X POST http://localhost:8080/v1/message \
-H "Content-Type: application/json" \
-d '{
"from": "coordinator",
"to": "researcher",
"content": "Analyze the latest threat report",
"metadata": {"task_id": "abc-123"}
}'
| Field | Type | Required | Description |
|---|---|---|---|
from |
string | yes | Sender agent name |
to |
string | yes | Recipient agent name |
content |
string | yes | Message content |
signature |
string | conditional | Base64-encoded Ed25519 signature. Required when require_signature: true |
timestamp |
string | no | RFC 3339 timestamp. Auto-generated if omitted |
metadata |
object | no | Arbitrary key-value pairs passed through to the audit log |
Signing payload:
The signature covers the canonical string from\nto\ncontent\ntimestamp using Ed25519:
Response (200 — delivered):
{
"status": "delivered",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"policy_decision": "allow",
"rules_triggered": [],
"verified_sender": true,
"quarantine_id": "",
"expires_at": ""
}
Response (202 — quarantined):
{
"status": "quarantined",
"message_id": "550e8400-e29b-41d4-a716-446655440001",
"policy_decision": "content_quarantined",
"rules_triggered": [
{"rule_id": "IAP-002", "name": "PII in agent messages", "severity": "high"}
],
"quarantine_id": "q-abc123",
"expires_at": "2026-03-07T10:00:00Z"
}
Response (403 — blocked):
{
"status": "blocked",
"message_id": "550e8400-e29b-41d4-a716-446655440002",
"policy_decision": "content_blocked",
"rules_triggered": [
{"rule_id": "IAP-001", "name": "Relay injection", "severity": "critical"}
]
}
Policy decisions¶
| Decision | HTTP | Meaning |
|---|---|---|
allow |
200 | Clean content, delivered |
content_flagged |
200 | Medium-severity finding, delivered with warning |
content_quarantined |
202 | High-severity, held for human review |
content_blocked |
403 | Critical-severity, rejected |
identity_rejected |
403 | Invalid signature or unknown agent (enforce mode) |
signature_required |
401 | Unsigned message when signatures are enforced |
acl_denied |
403 | Sender not authorized to message recipient |
agent_suspended |
403 | Sender is suspended |
recipient_suspended |
403 | Recipient is suspended |
Pipeline order¶
The pipeline runs checks from cheapest to most expensive. If any check fails, subsequent checks are skipped:
- Rate limit (~1ns)
- Identity verification (~120us)
- Suspension check
- ACL evaluation
- Content scan — 175 Aguara rules (~8ms)
- Blocked content filter (per-agent categories)
- Split injection detection (multi-message scan)
- Rule overrides (from config)
- History escalation (3+ blocks in 1h)
- Audit log write
- Anomaly detection (background)
Agent CRUD API¶
GET /v1/agents¶
List all agents.
[
{
"name": "coordinator",
"description": "Orchestrator",
"can_message": ["researcher", "coder"],
"suspended": false,
"has_key": true,
"tags": ["prod"],
"location": "us-east-1"
}
]
GET /v1/agents/{name}¶
Get agent details. Returns 404 if not found.
POST /v1/agents¶
Create a new agent.
curl -X POST http://localhost:8080/v1/agents \
-H "Content-Type: application/json" \
-d '{
"name": "new-agent",
"description": "Research assistant",
"can_message": ["coordinator"],
"blocked_content": ["credentials"],
"allowed_tools": ["read_file", "search_files"],
"location": "us-east-1",
"tags": ["staging"]
}'
| Status | Meaning |
|---|---|
| 201 | Agent created |
| 400 | Invalid name (must match ^[a-zA-Z0-9][a-zA-Z0-9_-]*$) |
| 409 | Agent already exists |
PUT /v1/agents/{name}¶
Partial update — only provided fields are changed.
curl -X PUT http://localhost:8080/v1/agents/researcher \
-H "Content-Type: application/json" \
-d '{
"description": "Updated description",
"blocked_content": ["credentials", "pii"]
}'
Uses pointer fields internally (*string, *bool) so omitted fields are preserved.
DELETE /v1/agents/{name}¶
Delete an agent and persist to config.
| Status | Meaning |
|---|---|
| 204 | Deleted |
| 404 | Not found |
POST /v1/agents/{name}/keys¶
Rotate the agent's Ed25519 keypair. Revokes the old key and generates a new one.
POST /v1/agents/{name}/suspend¶
Toggle suspension state.
Quarantine API¶
GET /v1/quarantine/{id}¶
Get the status and details of a quarantined message.
Health & Monitoring¶
GET /health¶
GET /metrics¶
Prometheus-format metrics.
| Metric | Type | Description |
|---|---|---|
oktsec_messages_total |
counter | Total messages processed, by verdict |
oktsec_message_latency_seconds |
histogram | End-to-end pipeline latency |
oktsec_rules_triggered_total |
counter | Detection rule triggers, by rule ID |
oktsec_rate_limit_hits_total |
counter | Rate limit rejections |
oktsec_quarantine_pending |
gauge | Current pending quarantine items |
oktsec_signature_verified_total |
counter | Signature verification results |
Example Prometheus scrape config:
scrape_configs:
- job_name: oktsec
static_configs:
- targets: ['localhost:8080']
metrics_path: /metrics
Dashboard endpoints¶
The dashboard is served at /dashboard with SSE for live updates. These are internal endpoints used by the HTMX UI:
| Path | Method | Description |
|---|---|---|
/dashboard |
GET | Overview page |
/dashboard/login |
GET/POST | Access code authentication |
/dashboard/events |
GET | Events page with SSE streaming |
/dashboard/rules |
GET | Rule categories |
/dashboard/rules/{category} |
GET | Rules in a category |
/dashboard/rules/detail/{id} |
GET | Rule detail page |
/dashboard/agents |
GET | Agent list |
/dashboard/agents/{name} |
GET | Agent detail |
/dashboard/graph |
GET | Communication topology |
/dashboard/settings |
GET | Settings page |
/dashboard/audit |
GET | Security audit |
/dashboard/discovery |
GET | MCP client discovery |
Webhook events¶
Oktsec sends webhook notifications for configured events.
Event types: message_blocked, message_quarantined, agent_risk_elevated, rule_triggered.
Payload:
{
"event": "message_blocked",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"from": "researcher",
"to": "coordinator",
"severity": "critical",
"rule": "IAP-001",
"rule_name": "Relay injection",
"category": "inter-agent",
"timestamp": "2026-03-06T15:00:00Z"
}
MCP Tools¶
When running as an MCP server (oktsec mcp), these tools are available:
scan_message¶
Scan content for security threats.
| Parameter | Type | Required | Description |
|---|---|---|---|
content |
string | yes | Content to scan |
from |
string | no | Sender agent name |
to |
string | no | Recipient agent name |
Returns verdict (clean, flag, quarantine, block) and triggered rules.
list_agents¶
List all configured agents with ACLs and status. No parameters.
audit_query¶
Query the audit log.
| Parameter | Type | Required | Description |
|---|---|---|---|
status |
string | no | Filter by status |
agent |
string | no | Filter by agent |
limit |
int | no | Max entries |
get_policy¶
Get the security policy for a specific agent.
| Parameter | Type | Required | Description |
|---|---|---|---|
agent |
string | yes | Agent name |
verify_agent¶
Verify an Ed25519 signature.
| Parameter | Type | Required | Description |
|---|---|---|---|
agent |
string | yes | Agent name |
from |
string | yes | Sender |
to |
string | yes | Recipient |
content |
string | yes | Message content |
timestamp |
string | yes | RFC 3339 timestamp |
signature |
string | yes | Base64 Ed25519 signature |
review_quarantine¶
Manage quarantined messages.
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | yes | list, detail, approve, or reject |
id |
string | conditional | Quarantine item ID (for detail/approve/reject) |
limit |
int | no | Max items for list action |
status |
string | no | Filter for list action |