Documentation Index
Fetch the complete documentation index at: https://docs.feral.sh/llms.txt
Use this file to discover all available pages before exploring further.
Status: Stable — The three autonomy modes and the ApprovalManager are production-ready.
Autonomy Levels
FERAL’s autonomy system controls how much freedom the agent has to act without human approval. Three modes — strict, hybrid, and loose — determine which tools auto-execute and which require explicit confirmation.
Strict Mode
Every tool call requires user approval. The agent proposes an action and waits.
User: "What's the weather in NYC?"
Agent: I'd like to call the weather API for NYC. Approve? [✓ / ✗]
User: ✓
Agent: It's 72°F and sunny in New York.
Best for: first-time setup, untrusted environments, auditing all agent behavior.
// ~/.feral/settings.json
{ "autonomy": { "mode": "strict" } }
Hybrid Mode
Safe actions (passive + active permission tiers) execute automatically. Risky actions (privileged + dangerous) require approval.
User: "Search for flights to Tokyo and book the cheapest one."
Agent: [auto] Searching flights... found 3 options.
Agent: The cheapest is $450 on ANA. I need approval to book. Approve? [✓ / ✗]
This is the default mode. Most users stay here — the agent handles research and information retrieval instantly, but pauses before actions with real-world consequences.
What Auto-Executes in Hybrid
| Action | Tier | Auto? |
|---|
| Search the web | passive | Yes |
| Read memory | passive | Yes |
| Get weather | passive | Yes |
| Send a chat message | active | Yes |
| Create a file | active | Yes |
| Run a shell command | privileged | No — asks first |
| Send an email | privileged | No — asks first |
| Delete files | dangerous | No — asks first |
| Make a purchase | dangerous | No — asks first |
Loose Mode
Everything except dangerous-tier tools auto-executes. The agent runs on full autopilot for most tasks.
User: "Clean up my Downloads folder — delete anything older than 30 days."
Agent: [auto] Listing files... found 47 files older than 30 days.
Agent: [auto] Moving 47 files to trash... done.
dangerous tools still require approval even in loose mode. See Security Model for the hard-coded deny list.
Configuration
Environment Variable
export FERAL_AUTONOMY=hybrid # strict | hybrid | loose
The env var takes precedence over the config file, useful for per-session overrides:
FERAL_AUTONOMY=strict feral start
Config File
// ~/.feral/settings.json
{ "autonomy": { "mode": "hybrid" } }
Per-Session Override
Clients can request an autonomy level during session initialization:
from feral_sdk import FeralClient
async with FeralClient("http://localhost:9090") as client:
session = await client.create_session(autonomy="strict")
The server enforces that a session cannot escalate beyond the server-level setting. If the server is hybrid, a session can request strict (more restrictive) but not loose (less restrictive).
ApprovalManager
The ApprovalManager handles approval requests and maintains a list of standing approvals — pre-authorized tool+argument patterns that skip the approval prompt.
from feral_core.security import ApprovalManager
manager = ApprovalManager()
manager.grant_standing(
tool="shell_exec",
pattern={"command": "ls *"}, # glob match on args
expires_in=3600, # seconds; None = permanent
)
approved = manager.check("shell_exec", {"command": "ls -la ~/Documents"})
# approved == True (matches "ls *" pattern)
Standing approvals are stored in ~/.feral/exec_approvals.db and persist across restarts. They are managed today through the Python ApprovalManager API (used by skills, channels, and the orchestrator); a public CLI/REST surface for granting and listing them is tracked as a follow-up.
Approval Inbox API
Every blocked tool call also surfaces in a non-chat approval inbox so a web UI, mobile client, or automation can resolve it without typing into a chat session. See REST API → Approvals (Execution Inbox) for the full reference.
| Method | Path | Description |
|---|
GET | /api/approvals | List pending requests (optional session_id, limit). |
POST | /api/approvals/{request_id}/approve | Approve and execute. |
POST | /api/approvals/{request_id}/reject | Reject without executing. |
curl http://localhost:9090/api/approvals?session_id=s-abc123
curl -X POST http://localhost:9090/api/approvals/apr_01HXYZ/approve \
-H "Content-Type: application/json" \
-d '{ "session_id": "s-abc123" }'
Both write endpoints accept an optional { "session_id": "…" } body. When supplied it must match the session that owns the pending request, or the call returns 409 session_mismatch. Resolving an unknown request returns 404.
Approval Flow
When a tool call needs approval, the following sequence occurs:
enforce_safety() determines the call requires approval and a pending request is created with a stable request_id.
- The Brain sends an
approval_request frame to the active chat session and the same request becomes visible at GET /api/approvals.
- The user responds, either by acknowledging in chat or by hitting
POST /api/approvals/{request_id}/approve or …/reject.
- If approved, the tool executes and the result flows back normally.
- If denied, the agent receives a “tool denied” signal and re-plans.
{
"type": "approval_request",
"payload": {
"request_id": "apr_abc123",
"tool": "shell_exec",
"args": {"command": "rm -rf /tmp/old-cache"},
"permission_tier": "privileged",
"reason": "Shell command execution requires approval in hybrid mode"
}
}
Escalation Rules
| Server Setting | Session Request | Effective Level |
|---|
strict | strict | strict |
strict | hybrid | strict (capped) |
hybrid | strict | strict |
hybrid | hybrid | hybrid |
hybrid | loose | hybrid (capped) |
loose | any | as requested |