Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Permission Model

Koyal uses a review-first permission model. No trade executes without an explicit approval step. The system fails closed — halt is the default state on first boot.


Core Concepts

Global Halt Switch

The halt switch blocks all proposal execution globally.

  • Default: halted on first boot until setup is complete
  • CLI: koyal halt on / koyal halt off
  • API: POST /api/halt {"halted": true, "reason": "..."}
  • Dashboard: prominent red Halt button in the header
koyal halt status
# {"halted": false, "reason": null}

koyal halt on --reason "flash crash detected"
# Trading is now halted

Proposal Flow

Every trade follows this path:

AgentTick → TradeProposal (pending)
    → PermissionEngine.check()
        → Allow  → execute()   → write ledger
        → Deny   → reject()    → log reason
        → Prompt → approval queue → operator review → allow/deny

Prompt is the most common result for new bots or large trades. The operator reviews in the dashboard or via CLI and responds explicitly.

Approval Queue

Pending approvals appear in:

  • GET /api/permissions — list
  • POST /api/approvals/respond {"requestId": "...", "decision": "allow"} — respond
  • Dashboard: ApprovalBanner at top of page

Wallet Roles

Each wallet assigned to a bot has a role:

RoleDescription
ObserveRead-only. Balance queries only. No trade permissions.
TradeCan execute swaps up to bot risk limits.
SweepCan move funds out. Requires elevated approval.

Bot Risk Config

Each bot has a risk config:

{
  "maxPositionPct": 2.0,
  "maxDrawdownPct": 5.0,
  "maxDailyTrades": 10,
  "maxSlippageBps": 100
}

The PermissionEngine enforces these limits before any trade executes.


PermissionEngine

PermissionEngine in koyal-runtime runs on every tick:

  1. Check global halt — deny immediately if halted
  2. Check bot lifecycle state — deny if not live
  3. Validate wallet role for the requested operation
  4. Check risk config bounds (position size, drawdown, daily trade count)
  5. Check bot-scoped policy rules from vault bots/<id>.md
  6. Return Allow, Deny(reason), or Prompt{request_id}

Security Notes

  • Private keys are never stored in plain text. koyal-providers uses AES-256-GCM for encrypted credential storage.
  • The gateway binds to 127.0.0.1 by default. Binding to 0.0.0.0 requires explicit operator action.
  • All API routes that modify state require the gateway to be in a non-halted state, or the route itself handles halt semantics.
  • The MCP server only exposes read-safe tools by default; write tools require explicit bot context.