Tiresias User & Developer Guide
AI Agent Security Platform: SoulAuth | SoulWatch | SoulGate
Version: 1.0 Last updated: 2026-03-22
Table of Contents
- Getting Started
- SoulAuth: Agent Identity & Authorization
- SoulWatch: Runtime Monitoring
- SoulGate: API Gateway
- API Reference Quick Start
- SDK & CLI
- Dashboard
- Best Practices
- Troubleshooting
1. Getting Started
What is Tiresias?
Tiresias is a security platform purpose-built for AI agent systems. If you're deploying autonomous agents - whether they read documents, execute code, call APIs, or talk to other agents - Tiresias gives you the identity, authorization, monitoring, and gateway controls you need to keep those agents safe, accountable, and under control.
The platform is composed of three products:
| Product | What it does |
|---|---|
| SoulAuth | Identity and authorization for AI agents. Every agent gets a cryptographic identity (SoulKey), and every action is evaluated against fine-grained policies. |
| SoulWatch | Runtime behavioral monitoring. Detects anomalies, enforces Sigma-compatible detection rules, and can automatically quarantine agents that go off-script. |
| SoulGate | A security gateway that sits in front of your agent-facing APIs. Handles rate limiting, circuit breaking, prompt injection detection, and full audit logging. |
You can use all three together or adopt them independently. They share a common identity layer (SoulKeys) and audit infrastructure, so the more you use, the richer your security posture becomes.
Account Setup
- Join the beta waitlist at tiresias.network. We review applications on a rolling basis.
- Receive your invite via email. The invite includes your tenant ID and a link to set up your account.
- Sign in via SSO (Google) to access the Tiresias dashboard.
- Create your first SoulKey from the dashboard's Keys panel (or via the CLI).
First Steps
Once you have access, here's the quickest path to a working integration:
Step 1: Get your SoulKey
From the dashboard, navigate to Keys > Issue New Key. Choose a persona name for your agent (e.g., alfred, researcher, code-reviewer). The system generates a SoulKey in the format:
sk_agent_<tenant>_<persona>_<hex32>
Copy it immediately - you won't be able to see the full key again.
Step 2: Make your first auth request
curl -H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
https://tiresias.network/v1/auth/identity
If everything is set up correctly, you'll get back a JSON response with your agent's identity, tenant, and active policies.
Step 3: Understand capability tokens
When your agent needs to access a protected resource, it first evaluates access (Step 2 above returns a short-lived capability token), then presents that token on subsequent requests. Tokens are JWT-based, ES256-signed, and expire in 300--900 seconds. This means your agent re-proves its authorization frequently, which limits the blast radius if a token is compromised.
2. SoulAuth: Agent Identity & Authorization
SoulAuth is the identity and authorization backbone. Every agent in your system gets a SoulKey, and every action that agent takes is evaluated against a policy engine before it's allowed to proceed.
Authentication Flow
The core flow has four steps:
Agent Tiresias
| |
|-- 1. Resolve identity -------->| GET /v1/auth/identity
|<-------- identity confirmed ---|
| |
|-- 2. Request access ---------->| POST /v1/auth/evaluate
|<--- capability token (JWT) ----|
| |
|-- 3. Use capability token ---->| X-Capability-Token header
|<-------- resource response ----|
| |
|-- 4. Token expires ----------->| re-evaluate when needed
| |
Step 1: Resolve Identity
Before your agent does anything, it identifies itself:
curl -H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
https://tiresias.network/v1/auth/identity
Response:
{
"agent_id": "agt_7f3a...",
"tenant": "acme",
"persona": "alfred",
"status": "active",
"policies": ["default", "memory-access", "code-execution"],
"created_at": "2026-01-15T08:30:00Z"
}
This step confirms the SoulKey is valid and returns the agent's identity context.
Step 2: Request Access
When your agent needs to perform a specific action, it requests access:
curl -X POST https://tiresias.network/v1/auth/evaluate \
-H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"resource": "memory",
"action": "read",
"scope": "cs:algorithms"
}'
Response (granted):
{
"decision": "GRANT",
"capability_token": "eyJhbGciOiJFUzI1NiIs...",
"expires_in": 300,
"scopes_granted": ["memory:read:cs:algorithms"],
"session_id": "ses_9c4e..."
}
Response (denied):
{
"decision": "DENY",
"reason": "scope_not_permitted",
"policy": "memory-access",
"required_scope": "cs:algorithms",
"available_scopes": ["cs:basics", "cs:data-structures"]
}
Step 3: Use Capability Token
Include the token on requests to protected resources:
curl -H "X-Capability-Token: eyJhbGciOiJFUzI1NiIs..." \
https://tiresias.network/v1/memory/cs/algorithms
The resource server validates the token's signature, expiry, revocation status, and scope before serving the request.
Step 4: Token Expiry
Capability tokens are intentionally short-lived (300--900 seconds). When a token expires, your agent simply re-evaluates:
import time
token = soulauth.evaluate(resource="memory", action="read", scope="cs:algorithms")
# Use the token...
# Later, check if it's still valid
if token.expires_at < time.time():
token = soulauth.evaluate(resource="memory", action="read", scope="cs:algorithms")
This is by design. Short-lived tokens limit the damage window if a token is leaked.
SoulKey Basics
Format
Every SoulKey follows this format:
sk_agent_<tenant>_<persona>_<hex32>
sk_agent_: fixed prefix identifying this as a SoulAuth agent key<tenant>: your organization's tenant identifier (e.g.,acme)<persona>: the agent's identity name (e.g.,alfred,researcher)<hex32>: 32 hex characters of cryptographic randomness
Example: sk_agent_acme_alfred_3f8a9b2c1d4e5f6a7b8c9d0e1f2a3b4c
Storage Best Practices
- Do store SoulKeys in environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, etc.)
- Do inject keys at runtime, never at build time
- Don't hardcode keys in source code
- Don't commit keys to git repositories
- Don't log keys in plaintext
import os
# Good
soulkey = os.environ["SOULAUTH_API_KEY"]
# Bad -- never do this
soulkey = "sk_agent_acme_alfred_3f8a9b2c..."
One Key Per Agent
Each SoulKey represents a single agent identity (persona). If you have three agents - a researcher, a code reviewer, and a deployer - issue three separate keys. This gives you:
- Per-agent audit trails
- Per-agent policy enforcement
- The ability to revoke one agent without affecting others
Self-Inspection
Any agent can inspect its own identity:
curl -H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
https://tiresias.network/v1/auth/whoami
Response:
{
"agent_id": "agt_7f3a...",
"tenant": "acme",
"persona": "alfred",
"status": "active",
"key_issued_at": "2026-01-15T08:30:00Z",
"policies": [
{
"name": "memory-access",
"resources": ["memory"],
"actions": ["read", "write"],
"scopes": ["cs:*"]
}
],
"session": {
"id": "ses_9c4e...",
"started_at": "2026-03-22T14:00:00Z"
}
}
This is useful for debugging ("why can't my agent access X?") and for agents that need to understand their own permissions before making decisions.
Policy Model
Tiresias uses a hierarchical access control model built on three dimensions: resources, actions, and scopes.
Resources, Actions, and Scopes
| Dimension | What it represents | Examples |
|---|---|---|
| Resource | The thing being accessed | memory, code, api, file, model |
| Action | What operation is performed | read, write, execute, delete, list |
| Scope | The boundary or namespace | cs:algorithms, prod:us-east, team:security |
A policy grant looks like: resource:action:scope
# Example policy definition
name: researcher-policy
rules:
- resource: memory
actions: [read, list]
scopes: ["cs:*", "ml:*"]
- resource: code
actions: [read]
scopes: ["repos:public:*"]
- resource: api
actions: [execute]
scopes: ["search:web"]
Wildcard Support
Use wildcards to grant broad access where appropriate:
| Pattern | Meaning |
|---|---|
scope: "*" |
All scopes for this resource:action |
scope: "cs:*" |
All scopes under the cs namespace |
actions: ["*"] |
All actions on the resource (use carefully) |
Role-Based Policies
For common patterns, define role templates and assign them to agents:
roles:
reader:
rules:
- resource: "*"
actions: [read, list]
scopes: ["*"]
operator:
inherits: reader
rules:
- resource: code
actions: [execute]
scopes: ["ops:*"]
- resource: api
actions: [execute]
scopes: ["internal:*"]
Agents inherit all rules from their assigned role, plus any agent-specific overrides.
JIT (Just-In-Time) Constraints
For sensitive operations, add time-based and session-based constraints:
rules:
- resource: database
actions: [write, delete]
scopes: ["prod:*"]
constraints:
time_window:
start: "09:00"
end: "17:00"
timezone: "America/Los_Angeles"
session_binding: required
node_restriction: ["node-us-east-1", "node-us-east-2"]
max_uses: 10
- Time windows: restrict when the action is permitted
- Session binding: the capability token is tied to a specific session
- Node restrictions: the request must originate from approved infrastructure
- Max uses: the token can only be used N times
Capability Tokens (JWT)
Capability tokens are the currency of authorization in Tiresias. When an agent's access request is granted, SoulAuth issues a signed JWT that the agent presents on subsequent requests.
Token Structure
Tokens are ES256-signed JWTs with these claims:
| Claim | Description | Example |
|---|---|---|
iss |
Issuer | tiresias.network |
sub |
Subject (SoulKey ID) | sk_7f3a... |
tid |
Tenant ID | acme |
pid |
Persona ID | alfred |
scp |
Granted scopes (array) | ["memory:read:cs:algorithms"] |
sid |
Session ID (optional) | ses_9c4e... |
jti |
Unique token ID | tok_8b2f... |
iat |
Issued at (Unix timestamp) | 1711108800 |
exp |
Expires at (Unix timestamp) | 1711109100 |
Token Validation
When a resource server receives a capability token, it performs validation in this order:
- Signature check: verify the ES256 signature against Tiresias's public key
- Expiry check: reject if
exp< current time - Revocation check: verify the
jtihasn't been revoked - Scope match: confirm the requested resource:action:scope is covered by the token's
scpclaim
If any check fails, the request is denied with an appropriate error.
Session Binding
If a token includes a sid (session ID), the resource server must also verify that the request includes an X-Session-ID header matching the token's sid. This prevents token theft across sessions.
# Token was issued with sid="ses_9c4e..."
curl -H "X-Capability-Token: eyJhbGciOi..." \
-H "X-Session-ID: ses_9c4e..." \
https://tiresias.network/v1/memory/cs/algorithms
Delegation & Escalation
Sometimes one agent needs to temporarily grant another agent access to resources it wouldn't normally reach. Tiresias supports this through delegation.
Use Cases
- Incident response: a triage agent needs temporary access to production logs
- Break-glass: an operator agent needs emergency write access to a locked-down system
- Collaboration: two agents working together on a task need overlapping permissions
How It Works
# Agent requesting escalation
curl -X POST https://tiresias.network/v1/auth/escalate \
-H "X-Soulkey: sk_agent_acme_triage_..." \
-H "Content-Type: application/json" \
-d '{
"resource": "logs",
"action": "read",
"scope": "prod:*",
"reason": "incident-2026-0322-001",
"requested_ttl": 1800
}'
The grantor agent (or a human operator) approves the request via the delegation API or the dashboard:
# Grantor approving the delegation
curl -X POST https://tiresias.network/v1/auth/delegate \
-H "X-Soulkey: sk_agent_acme_admin_..." \
-H "Content-Type: application/json" \
-d '{
"escalation_id": "esc_4f2a...",
"approved": true,
"ttl": 1800
}'
Constraints
- Maximum TTL: delegated access expires after at most 1 hour, regardless of what's requested
- Audit trail: every delegation is logged with the reason, grantor, grantee, and TTL
- No re-delegation: a delegated permission cannot be further delegated to a third agent
- Revocable: the grantor can revoke the delegation at any time before it expires
3. SoulWatch: Runtime Monitoring
SoulWatch watches your agents in real time. It builds behavioral baselines, detects anomalies, enforces detection rules, and can automatically quarantine agents that exhibit suspicious behavior.
Event Feed
Connect to the real-time event feed via WebSocket:
const ws = new WebSocket("wss://tiresias.network/v1/watch/events", {
headers: {
"X-Soulkey": "sk_agent_acme_monitor_..."
}
});
ws.on("message", (data) => {
const event = JSON.parse(data);
console.log(`[${event.type}] ${event.agent} - ${event.summary}`);
});
Event Types
| Type | Description |
|---|---|
auth.grant |
An access request was granted |
auth.deny |
An access request was denied |
anomaly.detected |
A behavioral anomaly was flagged |
detection.triggered |
A Sigma rule matched |
quarantine.initiated |
An agent was quarantined |
quarantine.released |
A quarantine was lifted |
key.issued |
A new SoulKey was created |
key.revoked |
A SoulKey was revoked |
delegation.created |
A delegation was approved |
Event Payload
{
"event_id": "evt_8a3f...",
"type": "anomaly.detected",
"agent": "alfred",
"tenant": "acme",
"timestamp": "2026-03-22T14:32:10Z",
"summary": "RATE_SPIKE: 47 requests in 60s (baseline: 12)",
"severity": "medium",
"details": {
"anomaly_type": "RATE_SPIKE",
"observed_value": 47,
"baseline_value": 12,
"threshold_multiplier": 3.0,
"window_seconds": 60
}
}
Anomaly Types
SoulWatch detects eight categories of anomalous behavior:
1. RATE_SPIKE
Trigger: request rate exceeds 3x the agent's established baseline.
An agent that normally makes 10 requests per minute suddenly making 40+ suggests automation gone wrong, a compromised key, or an unintended loop.
2. OFF_HOURS
Trigger: activity outside the agent's typical operating hours.
If an agent has only ever been active during business hours (9 AM - 6 PM), a 3 AM burst of requests is suspicious and worth investigating.
3. NEW_RESOURCE
Trigger: accessing a resource the agent has never accessed before.
When an agent that only reads from memory suddenly starts hitting database:write, SoulWatch flags it. This can be legitimate (new feature rollout) or malicious (compromised agent exploring the environment).
4. SCOPE_ESCALATION
Trigger: requesting a scope the agent doesn't normally use.
An agent that normally operates within staging:* requesting access to prod:* is a potential lateral movement indicator.
5. DENIAL_SPIKE
Trigger: denial rate exceeds 2x the agent's baseline.
A sudden increase in denied requests often indicates an agent probing for permissions it doesn't have - a classic reconnaissance pattern.
6. BURST
Trigger: single-minute event count exceeds the agent's historical maximum.
Even within normal operating hours at normal rates, a single-minute burst can indicate a runaway loop or data exfiltration attempt.
7. IMPOSSIBLE_TRAVEL
Trigger: geo-location inconsistency between consecutive requests.
If an agent makes a request from us-east-1 and then 30 seconds later from ap-southeast-1, the key may have been compromised and is being used from multiple locations.
8. CREDENTIAL_STUFFING
Trigger: 5 or more failed authentication attempts from the same IP using different SoulKeys.
This pattern indicates an attacker systematically trying stolen or guessed keys from a single origin.
Behavioral Baselines
SoulWatch doesn't use static thresholds. Instead, it builds a behavioral profile for each agent based on observed activity.
What's Tracked
| Metric | How it's measured |
|---|---|
| Request rate | Average requests per minute over the baseline window |
| Typical resources | Set of resources the agent normally accesses |
| Typical scopes | Set of scopes the agent normally requests |
| Active hours | Hours of the day when the agent is typically active |
| Denial rate | Percentage of requests that result in denials |
| Burst size | Maximum single-minute request count observed |
Baseline Lifecycle
- Build period: baselines are constructed from 7 days of audit history
- Refresh cycle: baselines are automatically rebuilt every 6 hours
- Cold start: new agents have limited anomaly detection for their first 7 days of operation - this is intentional. SoulWatch needs real behavioral data before it can detect deviations from normal.
If you need detection coverage during the cold-start period, consider defining explicit Sigma rules (see below) that don't depend on baselines.
Sigma Rules
SoulWatch supports Sigma-compatible detection rules. If you're already using Sigma for SIEM detection, you can bring your rule syntax directly into Tiresias.
Rule Format
title: Excessive Memory Writes
id: rule_mem_write_spike
status: active
description: Detects agents writing to memory at an unusual rate
detection:
selection:
resource: memory
action: write
condition: selection
aggregation:
count: true
threshold: 50
window: 300 # 5 minutes
level: high
tags:
- data_exfiltration
- memory_abuse
Field Matching
Sigma rules support multiple matching modes:
| Mode | Syntax | Example |
|---|---|---|
| Exact | field: value |
resource: memory |
| Wildcard | field: "prod:*" |
scope: "prod:*" |
| Contains | field|contains: "admin" |
persona|contains: "admin" |
| Starts with | field|startswith: "sk_agent" |
key|startswith: "sk_agent" |
| Ends with | field|endswith: "_prod" |
scope|endswith: "_prod" |
| Numeric comparison | field > 100 |
request_count > 100 |
Aggregation
Count-based thresholds over time windows:
aggregation:
count: true
threshold: 50 # trigger if count exceeds this
window: 300 # within this many seconds
group_by: agent # count per agent (optional)
Managing Rules
Upload rules via the API:
curl -X POST https://tiresias.network/v1/watch/rules \
-H "X-Soulkey: sk_agent_acme_admin_..." \
-H "Content-Type: application/yaml" \
--data-binary @my-rule.yaml
Or store them directly in the database via the dashboard's rule editor.
Quarantine
When SoulWatch detects anomalous behavior, it can automatically take enforcement actions through the quarantine system.
Available Actions
| Action | Effect |
|---|---|
suspend_key |
Temporarily disables the SoulKey (reversible) |
revoke_key |
Permanently revokes the SoulKey (irreversible) |
kill_session |
Terminates the agent's active session |
force_reauth |
Requires the agent to re-authenticate |
rate_limit |
Applies a restrictive rate limit to the agent |
isolate |
Blocks the agent from accessing new resources |
reset_context |
Clears the agent's session context |
Auto-Release Timers
To prevent permanent lockouts from false positives, quarantine actions can have auto-release timers:
quarantine_policy:
on_rate_spike:
action: rate_limit
auto_release: 300 # release after 5 minutes
on_credential_stuffing:
action: suspend_key
auto_release: 3600 # release after 1 hour
on_impossible_travel:
action: kill_session
requires_approval: true # human must approve release
Manual Approval Gates
For high-severity anomalies, configure quarantine actions that require human approval before the agent is released. These show up in the dashboard's Quarantine panel with an "Approve Release" button.
Checking Quarantine Status
curl -H "X-Soulkey: sk_agent_acme_admin_..." \
https://tiresias.network/v1/enforcement/quarantine
Response:
{
"quarantines": [
{
"quarantine_id": "qtn_3a8f...",
"agent": "researcher",
"action": "rate_limit",
"reason": "RATE_SPIKE: 52 requests/min (baseline: 14)",
"started_at": "2026-03-22T14:32:10Z",
"auto_release_at": "2026-03-22T14:37:10Z",
"status": "active"
}
]
}
4. SoulGate: API Gateway
SoulGate is a security gateway that sits between your agents and the APIs they call. It provides seven layers of protection in a single deployment.
Security Pipeline (7 Stages)
Every request that passes through SoulGate is processed through a seven-stage pipeline. Each stage can pass the request forward, block it, or modify it.
Request
|
v
[1. Authentication] --> reject if invalid
|
v
[2. IP/Geo Access Control] --> reject if blocked origin
|
v
[3. Rate Limiting] --> reject if over limit (429)
|
v
[4. Circuit Breaker] --> reject if upstream unhealthy (503)
|
v
[5. Payload Inspection] --> reject if injection detected (403)
|
v
[6. Upstream Forwarding] --> proxy to your backend
|
v
[7. Audit Logging] --> record everything
|
v
Response
Stage 1: Authentication
Validates the request's authentication credentials. Supports:
- SoulKey (
X-Soulkeyheader) - Capability token (
X-Capability-Tokenheader) - API key (custom header, configurable per tenant)
Unauthenticated requests are rejected with 401 Unauthorized.
Stage 2: IP/Geo Access Control
Apply allowlists or denylists based on IP address, CIDR range, or geographic region:
ip_access:
mode: allowlist # or "denylist"
entries:
- 10.0.0.0/8 # internal network
- 203.0.113.0/24 # partner network
geo_block:
- CN
- RU
Stage 3: Rate Limiting
Sliding window rate limiting, configurable at multiple levels:
rate_limits:
tenant:
requests: 10000
window: 60 # per minute
per_agent:
requests: 500
window: 60
per_endpoint:
"/v1/memory/*":
requests: 100
window: 60
When a limit is hit, SoulGate returns 429 Too Many Requests with a Retry-After header indicating how many seconds the client should wait.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json
{"error": "rate_limited", "retry_after": 12}
Stage 4: Circuit Breaker
The circuit breaker protects upstream services from cascading failures. If your backend starts returning errors, SoulGate stops forwarding traffic and returns 503 Service Unavailable until the backend recovers.
States:
| State | Behavior |
|---|---|
| Closed | Normal operation. Requests pass through. Failures are counted. |
| Open | Backend is unhealthy. All requests immediately get 503. No traffic forwarded. |
| Half-Open | After a cooldown period, SoulGate sends a single probe request. If it succeeds, the circuit closes. If it fails, the circuit stays open. |
Configuration:
circuit_breaker:
failure_threshold: 5 # consecutive failures to trip
cooldown_seconds: 30 # time in open state before probing
probe_interval: 10 # seconds between probe attempts
success_threshold: 2 # consecutive successes to close
Anti-weaponization: the circuit breaker tracks failures per upstream, not per requester. A single attacker deliberately sending bad requests won't trip the breaker for everyone - only genuine upstream failures count.
Stage 5: Payload Inspection
SoulGate inspects request payloads for prompt injection attacks, covering the OWASP LLM Top 10 threat categories.
Prompt Injection Protection
SoulGate includes 40+ regex patterns that detect prompt injection attempts across eight categories:
| Category | What it catches |
|---|---|
| Direct injection | "Ignore previous instructions", "You are now..." |
| Indirect injection | Hidden instructions in retrieved documents or tool outputs |
| Jailbreak | DAN, roleplay exploits, hypothetical framing |
| System prompt extraction | "What are your instructions?", "Repeat your system prompt" |
| Delimiter escape | Attempting to close/open prompt delimiters |
| Encoding evasion | Base64, ROT13, Unicode tricks to bypass filters |
| Data exfiltration | Instructions to leak data via tool calls or outputs |
| Privilege escalation | "Act as admin", "Override safety settings" |
Risk Scoring
Each detected pattern has a severity score. SoulGate aggregates scores across all patterns found in a single request:
| Aggregated Score | Action |
|---|---|
| < 0.3 | Pass (no issues detected) |
| 0.3 - 0.7 | Warn (logged, request proceeds, alert raised) |
| > 0.7 | Block (request rejected with 403) |
Thresholds are tunable per tenant:
injection_protection:
block_threshold: 0.7
warn_threshold: 0.3
custom_patterns:
- pattern: "reveal.*api.*key"
severity: 0.9
category: data_exfiltration
Stage 6: Upstream Forwarding
Requests that pass all security stages are forwarded to your backend. SoulGate adds security headers to the forwarded request:
X-Tiresias-Agent: alfred
X-Tiresias-Tenant: acme
X-Tiresias-Session: ses_9c4e...
X-Tiresias-Request-ID: req_7f3a...
Your backend can use these headers for its own authorization logic or audit purposes.
Stage 7: Audit Logging
Every request - whether allowed or blocked - is recorded in the audit log with:
- Timestamp, request ID, agent, tenant
- Request method, path, headers (sensitive values redacted)
- Which pipeline stages passed/failed
- Response status code and latency
- Any anomalies or detections triggered
5. API Reference Quick Start
Here are the most common API calls to get you started. All endpoints use https://tiresias.network as the base URL.
Identity Resolution
Verify your agent's identity and check that your SoulKey is valid.
curl -H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
https://tiresias.network/v1/auth/identity
Self-Inspection
Get your agent's full identity profile, including policies and active session.
curl -H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
https://tiresias.network/v1/auth/whoami
Access Evaluation
Request access to a specific resource, action, and scope. Returns a capability token on success.
curl -X POST https://tiresias.network/v1/auth/evaluate \
-H "X-Soulkey: sk_agent_acme_alfred_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{"resource": "memory", "action": "read", "scope": "cs:algorithms"}'
Using a Capability Token
Present the token on requests to protected resources.
curl -H "X-Capability-Token: eyJhbGciOiJFUzI1NiIs..." \
https://tiresias.network/v1/memory/cs/algorithms
Check Quarantine Status
View active quarantines for your tenant.
curl -H "X-Soulkey: sk_agent_acme_admin_..." \
https://tiresias.network/v1/enforcement/quarantine
Request Escalation
Request temporary elevated access for a specific reason.
curl -X POST https://tiresias.network/v1/auth/escalate \
-H "X-Soulkey: sk_agent_acme_triage_..." \
-H "Content-Type: application/json" \
-d '{
"resource": "logs",
"action": "read",
"scope": "prod:*",
"reason": "incident-2026-0322-001",
"requested_ttl": 1800
}'
Upload a Sigma Rule
Add a custom detection rule.
curl -X POST https://tiresias.network/v1/watch/rules \
-H "X-Soulkey: sk_agent_acme_admin_..." \
-H "Content-Type: application/yaml" \
--data-binary @my-detection-rule.yaml
WebSocket Event Feed
Connect to the real-time event stream.
wss://tiresias.network/v1/watch/events
Header: X-Soulkey: sk_agent_acme_monitor_...
6. SDK & CLI
Python SDK
Install the SDK:
pip install soulauth
Basic usage:
from soulauth import SoulAuth
# Initialize the client
client = SoulAuth() # reads SOULAUTH_API_KEY from environment
# Check identity
identity = client.whoami()
print(f"Agent: {identity.persona}, Tenant: {identity.tenant}")
# Evaluate access
token = client.evaluate(
resource="memory",
action="read",
scope="cs:algorithms"
)
if token.granted:
# Use the token
response = client.request(
"GET",
"/v1/memory/cs/algorithms",
capability_token=token
)
print(response.json())
else:
print(f"Denied: {token.reason}")
# Token auto-refresh
with client.session(resource="memory", action="read", scope="cs:*") as session:
# The session automatically re-evaluates when the token expires
for item in session.get("/v1/memory/cs/algorithms").json():
process(item)
Async support:
from soulauth import AsyncSoulAuth
async def main():
client = AsyncSoulAuth()
token = await client.evaluate(resource="memory", action="read", scope="cs:*")
# ...
CLI
The CLI uses the SOULAUTH_API_KEY environment variable for authentication.
export SOULAUTH_API_KEY="sk_agent_acme_alfred_..."
Common commands:
# Check your identity
soulauth whoami
# Evaluate access
soulauth evaluate --resource memory --action read --scope "cs:algorithms"
# List your keys (admin only)
soulauth keys list
# Issue a new key
soulauth keys issue --persona researcher --policy default
# Suspend a key
soulauth keys suspend sk_agent_acme_researcher_...
# View active quarantines
soulauth quarantine list
# Upload a Sigma rule
soulauth rules upload my-rule.yaml
# Tail the event feed
soulauth watch --follow
Output formats:
# JSON output (default)
soulauth whoami --format json
# Table output (human-readable)
soulauth whoami --format table
# Quiet mode (just the value)
soulauth evaluate --resource memory --action read --scope "cs:*" --quiet
# Outputs: GRANT or DENY
7. Dashboard
The Tiresias dashboard is your control center for managing agents, policies, and security posture. Access it at tiresias.network/dashboard after signing in.
Overview
The landing page shows:
- Active agents: how many agents are currently active across your tenant
- Auth decisions: real-time grant/deny ratio with a 24-hour trend line
- Anomaly feed: live stream of detected anomalies, sorted by severity
- System health: status of SoulAuth, SoulWatch, and SoulGate services
Keys Management
Issue, inspect, and manage SoulKeys:
- Issue: create a new key for a persona, assign a policy, set an optional expiry date
- Inspect: view a key's metadata, last used timestamp, and associated policies
- Suspend: temporarily disable a key (reversible)
- Revoke: permanently invalidate a key (irreversible)
- Lifecycle view: see a key's full history - when it was created, when it was last used, any suspensions or escalations
Policy Editor
Write and validate policies in YAML with:
- Syntax validation: the editor checks your YAML in real time and flags errors
- Policy simulation: test a policy against sample requests before deploying it
- Version history: every policy change is versioned, with the ability to diff and roll back
- Templates: start from built-in role templates (reader, operator, admin) and customize
Quarantine Panel
Manage active quarantines:
- View all active quarantines with their trigger reason, severity, and countdown timer
- Release: manually release an agent from quarantine
- Approve: for quarantines requiring human approval, review the evidence and approve or deny release
- Extend: extend the quarantine timer if further investigation is needed
Audit Log Viewer
Search and explore the full audit trail:
- Search: full-text search across agent names, resources, scopes, and event types
- Filter: by time range, agent, event type, severity, decision (grant/deny)
- Export: download results as CSV or JSON for external analysis
- Detail view: click any event to see the full request/response payload, pipeline results, and related events
8. Best Practices
Identity & Keys
One SoulKey per agent identity. Never share keys between agents. If two agents share a key, you lose per-agent audit trails and can't revoke one without affecting the other.
Rotate keys periodically. Issue a new key, update your agent's configuration, verify the new key works, then revoke the old one. The SDK supports graceful key rotation with zero downtime.
Store keys in a secrets manager. Use AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, or similar. Inject at runtime via environment variables. Never commit keys to source control.
Authorization
Use the shortest reasonable token TTL. If your agent completes its work in under a minute, a 300-second token is generous. Longer TTLs mean longer windows of exposure if a token is leaked.
Prefer narrow scopes. Grant
cs:algorithmsinstead ofcs:*when possible. Wildcards are convenient but expand the blast radius of a compromised token.Use delegations for temporary access. When one agent needs to help another, use the delegation API. Never share SoulKeys between agents as a workaround for missing permissions.
Monitoring
Set operating windows. If your agent shouldn't run outside business hours, configure a time window constraint. SoulWatch will flag any OFF_HOURS activity, and the policy engine will deny requests outside the window.
Configure quarantine policies to match your risk tolerance. Start conservative (auto-quarantine on anomalies, short auto-release timers) and loosen as you learn your agents' normal behavior.
Monitor the anomaly feed during early deployment. The first few weeks will have false positives as baselines stabilize. Use this period to tune your Sigma rules and quarantine thresholds.
Write custom Sigma rules for your domain. The built-in anomaly types cover general patterns, but you know your system best. Write rules for patterns specific to your agents' roles and risks.
Gateway
Deploy SoulGate in front of every agent-facing API. Even internal APIs benefit from rate limiting, circuit breaking, and audit logging.
Tune prompt injection thresholds. The defaults (block at 0.7, warn at 0.3) work well for most deployments, but if your agents legitimately discuss security concepts, you may need to adjust to reduce false positives.
Use the circuit breaker to protect upstream services. If an agent hammers a failing API, the circuit breaker saves both the agent's time and the upstream's recovery.
9. Troubleshooting
"Invalid SoulKey"
Cause: the SoulKey is either malformed, revoked, suspended, or expired.
Steps:
- Verify the key format:
sk_agent_<tenant>_<persona>_<hex32> - Check for whitespace or truncation (common when copying from dashboards)
- Use the dashboard's Keys panel to verify the key's status
- If the key was revoked, issue a new one - revocation is irreversible
- If you suspect a hash mismatch, compare the SHA-512 hash of your key against the hash stored in the dashboard
"Token expired"
Cause: capability tokens are intentionally short-lived (300--900 seconds). This error means you're using a token past its expiry time.
Fix: re-evaluate access to get a fresh token. If using the SDK, enable auto-refresh:
with client.session(resource="memory", action="read", scope="cs:*") as session:
# Tokens are automatically refreshed before expiry
response = session.get("/v1/memory/cs/algorithms")
"Scope violation"
Cause: your capability token doesn't cover the resource, action, or scope you're requesting.
Steps:
- Decode your JWT to inspect the
scpclaim (usesoulauth token decode <token>) - Compare the token's scopes against the resource:action:scope you're requesting
- If you need broader access, re-evaluate with the correct scope
- If your policy doesn't grant the needed scope, update the policy in the dashboard
"Rate limited" (429)
Cause: you've exceeded the configured rate limit for your tenant, agent, or endpoint.
Fix:
- Read the
Retry-Afterheader to know how long to wait - Implement exponential backoff in your agent's request logic
- If the rate limit is too restrictive for legitimate use, adjust it in the dashboard or contact your tenant admin
import time
response = client.request("GET", "/v1/memory/cs/algorithms", capability_token=token)
if response.status_code == 429:
wait = int(response.headers.get("Retry-After", 10))
time.sleep(wait)
response = client.request("GET", "/v1/memory/cs/algorithms", capability_token=token)
"Circuit open" (503)
Cause: the upstream service behind SoulGate is unhealthy. The circuit breaker is protecting it from additional load.
Steps:
- This is not a Tiresias misconfiguration - your upstream is genuinely failing
- Check the health of the upstream service independently
- The circuit breaker will automatically probe the upstream at regular intervals
- Once the upstream recovers, the circuit closes and traffic flows normally
- Do not attempt to bypass the circuit breaker - it's protecting both your agent and the upstream
No anomaly detection for new agents
Cause: SoulWatch needs 7 days of behavioral data to build a baseline. During the cold-start period, behavioral anomaly detection (RATE_SPIKE, OFF_HOURS, etc.) is limited.
This is expected behavior, not a bug.
Mitigation: define explicit Sigma rules with absolute thresholds to provide coverage during the cold-start period:
title: Cold Start Rate Limit
description: Absolute rate limit for agents without established baselines
detection:
selection:
action: "*"
condition: selection
aggregation:
count: true
threshold: 100
window: 60
level: medium
Still stuck?
- Check the API status page for service health
- Review the audit log in the dashboard for detailed error context
- Reach out to support at
support@tiresias.network - Join the community Discord for peer help and discussion
Built by Saluca LLC. For more information, visit tiresias.network.