Skip to main content

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.
autonomy: hybrid

What Auto-Executes in Hybrid

ActionTierAuto?
Search the webpassiveYes
Read memorypassiveYes
Get weatherpassiveYes
Send a chat messageactiveYes
Create a fileactiveYes
Run a shell commandprivilegedNo — asks first
Send an emailprivilegedNo — asks first
Delete filesdangerousNo — asks first
Make a purchasedangerousNo — 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.
autonomy: loose

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.
MethodPathDescription
GET/api/approvalsList pending requests (optional session_id, limit).
POST/api/approvals/{request_id}/approveApprove and execute.
POST/api/approvals/{request_id}/rejectReject 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:
  1. enforce_safety() determines the call requires approval and a pending request is created with a stable request_id.
  2. The Brain sends an approval_request frame to the active chat session and the same request becomes visible at GET /api/approvals.
  3. The user responds, either by acknowledging in chat or by hitting POST /api/approvals/{request_id}/approve or …/reject.
  4. If approved, the tool executes and the result flows back normally.
  5. 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 SettingSession RequestEffective Level
strictstrictstrict
stricthybridstrict (capped)
hybridstrictstrict
hybridhybridhybrid
hybridloosehybrid (capped)
looseanyas requested