Troubleshooting & FAQ

Common issues

"Unauthorized" on every API call

Cause: Missing or invalid API key.

  • Verify the key starts with aaf_test_ or aaf_live_
  • Check that the agent is active (not suspended or revoked) on the Agents page
  • Ensure the Authorization: Bearer <key> header is set correctly
  • API keys are shown only once at creation — if lost, revoke and create a new one

"Forbidden" with role error

{ "error": "Forbidden", "required_role": "admin", "your_role": "viewer" }

Cause: Your user account doesn't have sufficient permissions.

  • Ask an owner or admin to promote your role from the Users page
  • Role hierarchy: owner > admin > member > viewer
  • Only owners can toggle the kill switch or import configs

Policy not matching actions

Symptoms: Actions are allowed when you expect them to be denied, or vice versa.

  1. Check scope: Policies only match actions within their scope (agent names, environments, action types). If the scope doesn't match, the policy is skipped entirely.
  2. Check priority: Lower number = higher priority (priority 1 evaluates before priority 100). However, deny always wins regardless of priority — a deny at priority 900 still blocks an allow at priority 1.
  3. Check enabled: Disabled policies are ignored. Toggle on the Policies page.
  4. Use dry-run: Send a test action to POST /api/v1/actions/dry-run to see which policies match and why.
  5. Check enforcement level: In L0 (Monitor), deny decisions are logged but not enforced.

Actions stuck in "pending_approval"

Cause: No one has approved or denied the action.

  • Check the Approvals page in the dashboard
  • If using Slack, verify the bot token and channel ID in Settings > Integrations
  • Approvals work without Slack — the dashboard UI is the default approval channel
  • Actions may expire if timeout_seconds is set in the policy rule

Gateway returns "connection refused"

Cause: The Gateway service is not running or the URL is wrong.

  • Verify the Gateway is running: curl http://localhost:8443/health
  • Check GATEWAY_URL in your environment or Settings > Integrations > Gateway
  • The Gateway is optional — TameFlare works in policy-only mode without it
  • If using Docker Compose, ensure both services are on the same network

"Secrets stored without encryption" warning

Cause: The SETTINGS_ENCRYPTION_KEY environment variable is not set.

  • Generate a key: openssl rand -hex 32
  • Set it as SETTINGS_ENCRYPTION_KEY in your environment
  • Restart the control plane
  • Existing secrets will be encrypted on next save

Login issues

"Invalid email or password":

  • Double-check your email and password
  • If you forgot your password, ask an admin to reset it from the Users page (there is no email-based reset since TameFlare is self-hosted)

"Account is suspended":

  • An admin has suspended your account. Contact your org owner.

Database errors after upgrade

Cause: Schema changes between versions.

  • Run pnpm db:push from apps/web/ to apply any new columns or tables
  • This is safe to run multiple times — it only adds missing schema elements
  • Back up your database file before upgrading (copy the .db file)

FAQ

Is TameFlare free?

Yes. TameFlare is source-available under the Elastic License v2 (ELv2). The Starter tier is free forever — self-host at no cost with 3 agents and 1,000 actions/month. Paid tiers unlock higher limits and features. See the pricing page.

Does TameFlare require the Gateway?

No. The Gateway is only needed if you want TameFlare to execute actions on behalf of agents (e.g., create GitHub issues, merge PRs). Without the Gateway, TameFlare works as a policy-only firewall — agents call TameFlare for a decision, then execute the action themselves.

Can I use TameFlare without Slack?

Yes. Approvals work directly in the dashboard UI without any external services. Slack integration is optional and additive — it sends notification messages but doesn't replace the dashboard.

What databases does TameFlare support?

TameFlare uses libSQL (SQLite-compatible) via Drizzle ORM. You can use:

  • SQLite (local file) — zero config, great for single-server deployments
  • Turso (hosted libSQL) — managed, with edge replicas and automatic backups

See the Deployment guide for details on switching between them.

How do I back up my data?

  • SQLite: Copy the .db file
  • Turso: Automatic backups included
  • Config: Use the dashboard Export feature to download policies and agents as JSON

Can multiple people use the dashboard?

Yes. TameFlare supports multiple users with role-based access control (RBAC). The first user to register becomes the owner. Additional users register at /register and default to the viewer role. Admins and owners can promote users from the Users page.

How do I write my first policy?

See the Your First Policy tutorial for a step-by-step guide, or the Writing Policies reference for the full YAML schema.

What happens when the kill switch is on?

All agent actions are immediately denied with the reason "Kill switch is active". The kill switch can only be toggled by an owner. It's designed as an emergency stop — use it if an agent is misbehaving and you need to halt all activity instantly.

How do I monitor TameFlare in production?

  • Health endpoint: GET /api/health returns DB and gateway status (wire into uptime monitoring)
  • Audit log: Every action, decision, and admin change is recorded
  • Webhook callbacks: Get notified on every decision via HTTP webhook
  • Dashboard auto-refresh: Overview page refreshes every 10 seconds

Can TameFlare prevent hallucination-based actions?

TameFlare evaluates the action spec (type, parameters, resource), not the LLM's reasoning. If a hallucinated action produces a valid action spec that violates a policy, it will be blocked. If the hallucinated action looks like a normal allowed action, TameFlare will allow it. Write policies that are specific enough to catch dangerous parameter combinations regardless of intent.

Can I change the deny-wins model?

No. Deny-wins is a deliberate security design choice — it ensures that a single safety policy cannot be overridden by a more permissive one. Use scopes to limit which actions a policy applies to, so deny rules only match the actions you intend.

When does the 5-minute token expiry start?

The token is issued after the decision. For allow decisions, the token is issued immediately. For requires_approval decisions, the token is issued after a human approves — the 5-minute clock starts at approval time, not at request time. Agents have 5 minutes from receiving the token to call execute.

Can I run Mode A and Mode B simultaneously?

Yes. Different agents can use different modes. An agent in Mode A calls TameFlare.execute() and the Gateway handles execution. An agent in Mode B checks the policy decision and executes the action itself. Both modes use the same policy engine and audit trail.

What happens if two policies both say "requires_approval"?

Both approval requirements must be satisfied. If Policy A requires approval from admin and Policy B requires approval from security-team, both groups must approve before the action proceeds.

What happens if TameFlare goes down?

By default, agents using the SDK will get a network error. The current behavior is fail-closed — if TameFlare is unreachable, the agent cannot get a decision token, so no actions execute via the Gateway. In Mode B, the agent could choose to proceed without TameFlare, but this is up to the agent's error handling.

Are webhook connector credentials safe?

In Mode A (full enforcement), credentials should live in the Gateway's environment, not in the action spec. The webhook example in the docs showing Authorization headers in parameters is a Mode B pattern where the agent holds its own credentials. In Mode A, configure credentials as Gateway environment variables.

What about GDPR and data deletion?

Action parameters are stored in the database as part of the action request record. The POST /api/maintenance/cleanup endpoint can purge old records based on AUDIT_RETENTION_DAYS. For targeted deletion of specific records, use direct database access. Consider enabling parameter redaction for sensitive fields.

What time zone do time-based policies use?

Time-based policy conditions evaluate against the server's local time (the timezone of the machine running the TameFlare control plane). For distributed teams, set your server to UTC and write time windows in UTC. Document the timezone in your policy descriptions.


Migration guides

Moving from SQLite to Turso

  1. Export your current config: GET /api/dashboard/export (saves policies + agents as JSON)
  2. Update TURSO_DATABASE_URL to your Turso URL and set TURSO_AUTH_TOKEN
  3. Run pnpm db:push from apps/web/ to create the schema on Turso
  4. Re-seed your org: register a new user (becomes owner), then import your config via POST /api/dashboard/import

Data is not automatically migrated. The export/import flow preserves policies and agents but not action history or audit events.

Moving from password auth to email/password auth

If you started with DASHBOARD_PASSWORD (legacy shared password):

  1. Remove DASHBOARD_PASSWORD from your environment
  2. Restart the control plane
  3. Register at /register — the first user becomes the org owner
  4. Invite team members by sharing the registration URL

Existing sessions from password auth will expire. Users must re-authenticate with email/password.

Adding encryption at rest

If you deployed without SETTINGS_ENCRYPTION_KEY and want to add it:

  1. Generate a key: openssl rand -hex 32
  2. Set SETTINGS_ENCRYPTION_KEY in your environment
  3. Restart the control plane
  4. Re-save your integration settings (Slack token, GitHub PAT) in Settings > Integrations — this re-encrypts them with the new key

Previously saved secrets in plaintext will still be readable. TameFlare auto-detects whether a value is encrypted or plaintext on read.

Upgrading between versions

TameFlare uses Drizzle ORM with db:push for schema management. After pulling a new version:

git pull
pnpm install
pnpm db:push    # from apps/web/
pnpm build

db:push is additive — it adds new columns and tables without dropping existing data. Check the changelog for any breaking changes that require manual migration steps.