Jesse A. Green / notebook

AutoGPT — Admin Guide

Generated September 2026 from Significant-Gravitas/AutoGPT at c035ab1

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for the people who deploy, operate, secure, and extend AutoGPT: administrators, platform engineers, architects, and block developers. It covers the AutoGPT Platform (autogpt_platform/) in depth and the legacy classic/ tree briefly. End-user tasks (building agents, AutoPilot, the Marketplace, scheduling) are in the companion User Guide.


1. Executive Summary

Aspect Summary
What it is A platform for building and running AI agents as visual graphs of blocks, plus a conversational builder (AutoPilot), a Marketplace, schedules, webhook triggers, credits/billing, and chat-bot bridges
Two products, one repo autogpt_platform/ (current, Polyform Shield license) and classic/ (original 2023 autonomous agent + forge + benchmark, MIT, unsupported)
Backend Python (>=3.10,<3.14), FastAPI, Prisma ORM on PostgreSQL + pgvector, RabbitMQ, a 3-node Redis cluster, FalkorDB (Graphiti memory), ClamAV, APScheduler-backed scheduler, Pyro-style internal RPC between services
Frontend Next.js (React, TypeScript) with an embedded Better Auth service issuing ES256 JWTs verified by the backend via JWKS
Deployment shapes (1) Multi-container Docker Compose from source; (2) experimental single-container appliance significantgravitas/autogpt; (3) the hosted cloud (BEHAVE_AS=cloud)
Scale of code ~7,000 files; 90 Prisma models; 219 migrations; 115 entries under backend/blocks/
State PostgreSQL (everything durable), RabbitMQ (execution queues), Redis (event bus, locks, caches), FalkorDB (memory graph), workspace/media storage (local or GCS)
Operational burden Moderate-to-high: ~10 backend service roles, 6 infrastructure services, secret management (Fernet ENCRYPTION_KEY), Prisma migrations on every upgrade, OAuth apps per integration

Important

The three most consequential operator facts: (1) the backend refuses to start without ENCRYPTION_KEY, and losing it makes every stored integration credential unreadable; (2) the appliance persists every generated secret in /data/config/runtime.env and has no in-place rotation; (3) BEHAVE_AS=local (the self-host default) bypasses subscription entitlement gating and is only appropriate for single-tenant installs.


2. Architecture

2.1 Component diagram (Compose deployment)

                         Browser
                            │ :3000
                ┌───────────▼────────────┐
                │ frontend (Next.js)     │  Better Auth (sessions, ES256 JWT,
                │  /api/auth/jwks        │  JWKS in platform."UserAuthJwks")
                └──────┬───────────┬─────┘
          REST :8006   │           │  WS :8001
        ┌──────────────▼──┐   ┌────▼─────────────┐
        │ rest_server     │   │ websocket_server │◄── Redis event bus
        │ FastAPI (/api,  │   │ (execution       │    (execution_event,
        │ /external-api,  │   │  updates)        │     notification_event)
        │ /health)        │   └──────────────────┘
        └──┬───────┬──────┘
           │ RPC   │ publish
           │       ▼
           │   ┌─────────┐   consume  ┌──────────────┐   ┌──────────────────┐
           │   │RabbitMQ │──────────► │ executor     │   │ copilot_executor │
           │   │  :5672  │──────────► │ :8002        │   │ :8008 (AutoPilot)│
           │   └─────────┘            └──────┬───────┘   └────────┬─────────┘
           │                                 │ RPC                │
     ┌─────▼──────────────┐       ┌──────────▼─────────┐  ┌───────▼───────┐
     │ database_manager   │◄──────┤ scheduler :8003    │  │ FalkorDB      │
     │ :8005 (DB RPC)     │       │ notification :8007 │  │ :6380 Graphiti│
     └─────┬──────────────┘       │ linking mgr :8009  │  └───────────────┘
           │                      └────────────────────┘
   ┌───────▼───────────┐   ┌──────────────────┐   ┌──────────────┐
   │ PostgreSQL :5432  │   │ Redis cluster    │   │ ClamAV :3310 │
   │ pgvector pg15     │   │ :17000-17002     │   │ (uploads)    │
   │ schema "platform" │   └──────────────────┘   └──────────────┘
   └───────────────────┘

2.2 Service inventory

All backend roles are the same image started with a different Poetry script.

Compose service Command Port Responsibility
migrate Prisma migrate — Applies migrations; other services wait for service_completed_successfully
rest_server rest 8006 FastAPI REST (/api/*), External API (/external-api), /health, webhook ingress, chat-bot webhook adapters
websocket_server ws 8001 Pushes execution events to browsers (/, /health)
executor executor 8002 Graph execution manager: consumes RabbitMQ, runs nodes, charges credits, resolves credentials
copilot_executor python -m backend.copilot.executor 8008 AutoPilot turn execution
database_manager db 8005 DB access service reached over internal RPC
scheduler_server scheduler 8003 Cron schedules (SQLAlchemy job store, pool of 3), periodic cleanup jobs
notification_server notification 8007 Email (Postmark) and push (VAPID) notifications
platform_linking_manager platform-linking-manager 8009 Links chat-platform users to accounts; bot profile only
frontend Next.js 3000 UI and Better Auth
db pgvector/pgvector:pg15 5432 PostgreSQL
redis-0/1/2 + redis-init redis:7 cluster 17000–17002 Event bus, locks, caches
rabbitmq rabbitmq:4.1.4 5672 Execution queues
falkordb falkordb/falkordb:latest 6380 (protocol), 3001 (UI) Graphiti temporal knowledge graph
clamav clamav/clamav-debian:latest 3310 Virus scanning for uploads

Additional roles defined in code (not separate Compose services by default): batch-executor (batch_executor_port 8011, polls LLM batch APIs), and the chat bridge (copilot_chat_bridge_port 8010).

poetry run app starts all roles in one process tree, in this order: DatabaseManager, Scheduler, BatchExecutor, NotificationManager, PlatformLinkingManager, WebsocketServer, AgentServer (REST), ExecutionManager, CoPilotChatBridge, CoPilotExecutor (the last runs in the foreground).

2.3 Repository layout

Path Contents
autogpt_platform/backend/backend/api/ FastAPI app (rest_api.py), WebSocket app (ws_api.py), features/* routers, external/ (External API v1), middleware/
.../backend/blocks/ Auto-discovered block modules (one package per provider)
.../backend/executor/ Execution manager, scheduler, billing, cost tracking, cluster lock, simulator, automod
.../backend/data/ Data access and domain logic (graphs, executions, credits, event bus, llm_registry/catalog.py, ...)
.../backend/integrations/ ProviderName, OAuth handlers (oauth/), webhook managers (webhooks/), credential store
.../backend/copilot/ AutoPilot: executor, tools, Graphiti memory, chat bots (bot/), evals
.../backend/sdk/ ProviderBuilder, block SDK re-exports
.../backend/cli/ Admin CLI (cli), oauth_tool, OpenAPI export
.../backend/util/settings.py The Config and Secrets settings models
autogpt_platform/backend/schema.prisma + migrations/ 90 models, 32 enums, 219 migrations
autogpt_platform/frontend/ Next.js app, Better Auth (src/lib/auth), Playwright tests
autogpt_platform/autogpt_libs/ Shared auth (JWKS verification, dependencies), utils
autogpt_platform/single-container/ Appliance build (docker-bake.hcl), runtime_config.py, probe.py, supervisor listeners, nginx
autogpt_platform/installer/ Appliance installer scripts
autogpt_platform/graph_templates/ Built-in graph templates
autogpt_platform/analytics/ Analytics SQL views
classic/ forge/, original_autogpt/, direct_benchmark/
docs/ platform/, integrations/ (generated block docs), content/ (classic/forge)

2.4 Execution flow

  1. A run is requested via REST (POST /api/graphs/{graph_id}/execute/{graph_version}), the External API, a schedule, a webhook trigger, or AutoPilot.
  2. The REST layer validates inputs and credentials, enforces the payment paywall where applicable, records an AgentGraphExecution, and publishes to RabbitMQ.
  3. The executor consumes the message (up to num_graph_workers, default 10), resolves starting nodes, and queues downstream nodes as their required inputs validate.
  4. Each node execution loads its block, injects credentials (never persisted into node I/O), charges credits (execution_cost_* settings), and records AgentNodeExecution + AgentNodeExecutionInputOutput.
  5. Progress is published on the Redis event bus (execution_event); the WebSocket server forwards it to subscribed browsers.
  6. A block failure yields on its error pin; errors inheriting from ValueError (BlockInputError, BlockExecutionError) are classified as user-fixable "expected failures".

Concurrency guards in Config:

Setting Default Meaning
num_graph_workers 10 Executor worker concurrency
max_concurrent_graph_executions_per_user 25 Per-user running graph cap
num_copilot_workers 5 AutoPilot executor concurrency
max_inflight_copilot_turns_per_user 15 Queued + running AutoPilot turns per user
max_running_copilot_turns_per_user 5 Concurrently running AutoPilot turns per user
cluster_lock_timeout 300 s Distributed lock TTL
requeue_by_republishing True Requeue strategy for RabbitMQ messages

2.5 Data Layer

  • ORM: Prisma (Python client), schema postgres/schema.prisma-style layout at backend/schema.prisma, default DB schema platform (DB_SCHEMA).
  • Database: PostgreSQL 15 with pgvector (embeddings for hybrid search).
  • Key model groups (90 models):
Group Models
Auth (Better Auth) AuthUser, AuthSession, AuthAccount, AuthVerification, AuthJwks
Users User, UserOnboarding, UserBalance, UserWorkspace, UserWorkspaceFile, UserWorkspaceFolder, UserAttribution, UserBriefing
Graphs AgentGraph, AgentNode, AgentNodeLink, AgentBlock, AgentPreset
Executions AgentGraphExecution, AgentNodeExecution, AgentNodeExecutionInputOutput, AgentNodeExecutionKeyValueData, PendingHumanReview
Library LibraryAgent, LibraryFolder
Store / Marketplace Profile, StoreListing, StoreListingVersion, StoreListingReview, SkillListing, SkillListingVersion, SkillListingFile, UnifiedContentEmbedding, SearchTerms
Billing CreditTransaction, CreditRefundRequest, PlatformCostLog, SubscriptionTrial, SubscriptionTrialClaim, OrganizationSubscription, OrgBalance, OrgCreditTransaction
Orgs & teams Organization, OrganizationAlias, OrganizationProfile, OrgMember, OrgInvitation, Team, TeamMember, TeamInvite, OrganizationSeatAssignment, TransferRequest, AuditLog
Integrations IntegrationCredential, IntegrationWebhook, APIKey
OAuth provider OAuthApplication, OAuthAuthorizationCode, OAuthAccessToken, OAuthRefreshToken
AutoPilot / chat ChatSession, ChatMessage, SharedChatFile, ChatLinkedShare, CoPilotUnderstanding, OnboardingBrainDump
Experts Expert, ExpertWorkflow, ExpertRoutine, ExpertSkillListing, ExpertCredential, ExpertPauseEvent, ExpertPod
Chat bots PlatformLink, PlatformUserLink, PlatformLinkToken, BotEvent, BotGuild, BotInstall
Notifications NotificationEvent, UserNotificationBatch, PushSubscription, AlertCondition
Analytics / experiments AnalyticsDetails, AnalyticsMetrics, ActivityEvent, ExperimentAssignment
Model registry LlmModelMigration

Warning

Don't hand-edit rows that carry encrypted payloads (IntegrationCredential) or Better Auth key material (AuthJwks, exposed as platform."UserAuthJwks" in the upgrade instructions). Use the CLI (rotate-encryption-key) or the documented DELETE FROM platform."UserAuthJwks"; reset only.

Search infrastructure. api/features/search/ provides a unified embedding table (UnifiedContentEmbedding) and unified_hybrid_search (semantic + BM25 lexical + recency + category scoring) across store agents, blocks, docs, library agents, workspace files, and chat sessions, exposed at /api/search/global. New content types add a ContentType enum value, a ContentHandler subclass registered in CONTENT_HANDLERS, and a background ensure_content_embedding call on write. Embeddings use store_embedding_model (default text-embedding-3-small).

2.6 Caching

Layer What is cached
Redis cluster Event bus channels (execution_event, notification_event), cluster locks, chat-bot thread subscriptions (7-day TTL), Teams activity-id dedup claims, PostHog flag definitions (posthog_flag_definition_cache=redis, refresh 30 s, TTL 600 s)
HTTP SecurityHeadersMiddleware sets cache-protection headers so sensitive API responses are not cached by browsers or proxies (only explicitly cacheable paths are allowed)
Appliance /data/cache Regenerable backend and Next.js caches; excluded from backups

3. System Requirements

Component Requirement
Container runtime Docker Engine or Docker Desktop; Podman is not supported
Docker Compose v2 (docker compose) for the from-source deployment
CPU architecture (appliance) linux/amd64 or linux/arm64 Linux containers
Backend Python (dev) >=3.10,<3.14, Poetry
Frontend (dev) Node.js + pnpm
Classic Python 3.12+, Poetry
PostgreSQL 15 with pgvector (image pgvector/pgvector:pg15)
RabbitMQ rabbitmq:4.1.4
Redis redis:7 in cluster mode (3 nodes)
Memory (appliance) Measured 5–6 GiB at startup/steady health, plus headroom
Storage (appliance) Image + growing /data + space for one full compressed backup; SSD-class recommended
Windows hosts Docker Desktop with WSL 2 engine (Hyper-V causes an unhealthy db)

Note

There is no measured minimum CPU count or supported concurrent-run ceiling for the appliance; performance depends on enabled services and workload.

Appliance fixed ceilings

Resource Limit
Prisma pool per backend role ≤ 5 connections (DB_CONNECTION_LIMIT range 1–5)
Scheduler job-store pools 2 × 3 SQLAlchemy connections
FalkorDB ≤ 25 queued queries, 1-second query timeout
Valkey / FalkorDB memory No appliance-level ceiling or eviction policy — monitor

4. Configuration Mastery

4.1 How configuration is loaded

Source Precedence (low → high)
.env.default (tracked, public, no secrets) 1
.env (per install, gitignored) 2
Compose environment: blocks (YAML anchors) 3
Shell environment 4

The backend settings are two Pydantic settings models in backend/util/settings.py: Config (behavior) and Secrets (credentials). Field names map to environment variables of the same name (conventionally upper-case, e.g. num_graph_workers ↔ NUM_GRAPH_WORKERS). .env.default only lists variables that must be set; everything else falls back to the code defaults below.

A ./secrets directory is also supported: each file ./secrets/<name> holds one secret value, loaded at startup — useful for Docker secrets.

4.2 Required settings

Variable Default Notes
DB_USER / DB_PASS / DB_NAME / DB_HOST / DB_PORT postgres / placeholder / postgres / localhost / 5432 Change DB_PASS from the published placeholder
DB_SCHEMA platform
DB_CONNECTION_LIMIT 12 (.env.default); appliance 1–5, default 5 Per-role Prisma pool
DB_CONNECT_TIMEOUT 60 Seconds
DB_POOL_TIMEOUT 300 Seconds
DATABASE_URL / DIRECT_URL built from the DB_* vars Includes ?schema=${DB_SCHEMA}&connect_timeout=...
PRISMA_SCHEMA postgres/schema.prisma
REDIS_HOST / REDIS_PORT / REDIS_PASSWORD localhost / 17000 (.env.default; code default 6379) / empty
RABBITMQ_DEFAULT_USER / RABBITMQ_DEFAULT_PASS dev values in .env.default Change for any shared deployment; guest is refused by the appliance
JWT_JWKS_URL http://localhost:3000/api/auth/jwks Must be HTTPS across untrusted networks
JWT_JWKS_ALGORITHMS ES256,RS256,EdDSA Asymmetric only
JWKS_ALLOW_INSECURE_TRANSPORT false Allows cleartext JWKS to a non-local host (logs a warning)
ENCRYPTION_KEY blank → generated Fernet key; backend refuses to start without it
UNSUBSCRIBE_SECRET_KEY blank → generated Signs email unsubscribe links
BETTER_AUTH_SECRET (frontend) blank → generated Better Auth signing secret

Caution

VAPID_PRIVATE_KEY / VAPID_PUBLIC_KEY ship as a dev-only keypair in .env.default. Regenerate before any non-local deployment:

poetry run python -c "
from py_vapid import Vapid; import base64
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
v = Vapid(); v.generate_keys()
raw_priv = v.private_key.private_numbers().private_value.to_bytes(32, 'big')
print('VAPID_PRIVATE_KEY=' + base64.urlsafe_b64encode(raw_priv).rstrip(b'=').decode())
raw_pub = v.public_key.public_bytes(Encoding.X962, PublicFormat.UncompressedPoint)
print('VAPID_PUBLIC_KEY=' + base64.urlsafe_b64encode(raw_pub).rstrip(b'=').decode())
"

Also set VAPID_CLAIM_EMAIL to a real mailbox (default mailto:[email removed] in .env.default).

4.3 Config reference (behavior)

Service ports and hosts

Setting Default
agent_api_host / agent_api_port 0.0.0.0 / 8006
websocket_server_host / websocket_server_port 0.0.0.0 / 8001
execution_manager_port 8002
execution_scheduler_port 8003
database_api_port 8005
notification_service_port 8007
copilot_executor_port 8008
platform_linking_service_port 8009
copilot_chat_bridge_port 8010
batch_executor_port 8011
pyro_host localhost
rabbitmq_host / rabbitmq_port / rabbitmq_vhost localhost / 5672 / /
redis_host / redis_port localhost / 6379
clamav_service_host / clamav_service_port localhost / 3310
ollama_host localhost:11434

Execution and concurrency

Setting Default
num_graph_workers 10
num_copilot_workers 5
fastapi_thread_pool_size 60
max_concurrent_graph_executions_per_user 25
max_inflight_copilot_turns_per_user 15
max_running_copilot_turns_per_user 5
requeue_by_republishing True
cluster_lock_timeout 300
rpc_client_call_timeout 300
pyro_client_comm_timeout / pyro_client_comm_retry / pyro_client_max_wait 15 / 100 / 30.0
llm_request_timeout_seconds 600
max_message_size_limit 16 MiB
execution_late_notification_threshold_secs 300
execution_late_notification_checkrange_secs 3600

Codex / ChatGPT subscription processes

Setting Default
codex_max_active_processes 4
codex_capacity_timeout_seconds 10
codex_startup_timeout_seconds 30
codex_control_timeout_seconds 60
codex_invocation_timeout_seconds 180
codex_copilot_turn_timeout_seconds 21600
codex_copilot_tool_timeout_seconds 900
codex_login_timeout_seconds 900
codex_auth_checkpoint_interval_seconds 0.25
codex_temp_root ""

Credits and billing

Setting Default
enable_auth True
enable_credit False
enable_subscription_credit_grant False
refund_credit_tolerance_threshold 500
low_balance_threshold 500
execution_cost_count_threshold 100
execution_cost_per_threshold 1
execution_counter_expiration_time 86400
expert_weekly_credit_budget_default 500
expert_spend_approval_threshold_default 250
expert_spend_approval_window week
refund_notification_email [email removed]
stripe_tier_reconcile_interval_hours 6

Files, scanning, moderation

Setting Default
upload_file_size_limit_mb 256
max_file_size_mb 100
clamav_service_enabled True
clamav_service_timeout 60
clamav_max_concurrency 10
clamav_mark_failed_scans_as_clean False
automod_enabled False
automod_api_url ""
automod_timeout / automod_retry_attempts / automod_retry_delay 30 / 3 / 1.0
automod_fail_open False
media_gcs_bucket_name "" (local store-media/)
workspace_storage_dir ""

URLs, CORS, environment

Setting Default
app_env local
behave_as local
platform_base_url "" (.env.default: http://localhost:8006)
frontend_base_url "" (.env.default: http://localhost:3000)
trusted_frontend_origins []
backend_cors_allow_origins ["http://localhost:3000"]
external_oauth_callback_origins ["http://localhost:3000"]
platform_link_base_url https://platform.agpt.co/link (.env.default: http://localhost:3000/link)

Feature flags and toggles

Setting Default
feature_flag_backend launchdarkly
posthog_flag_definition_cache redis
enable_example_blocks False
enable_agent_input_subtype_blocks True
use_agent_image_generation_v2 True
marketplace_require_canonical_category False
scheduler_startup_embedding_backfill True
autopilot_bot_teams_allow_unverified False

Force individual flags locally with FORCE_FLAG_<NAME>=true (or FORCE_ALL_FLAGS=true when APP_ENV=local); frontend equivalents use NEXT_PUBLIC_FORCE_FLAG_<NAME>.

Periodic cleanup jobs

Setting Default (hours)
cloud_storage_cleanup_interval_hours 6
oauth_token_cleanup_interval_hours 6
push_subscription_cleanup_interval_hours 24
platform_link_token_cleanup_interval_hours 6
block_error_rate_check_interval_secs 86400 (seconds)
execution_accuracy_check_interval_hours 24

Alerts and email senders

Setting Default
block_error_rate_threshold 0.5
block_error_include_top_blocks 3
platform_alert_discord_channel local-alerts
product_alert_discord_channel product-alerts
postmark_sender_email [email removed]
billing_sender_email AutoGPT <[email removed]>
product_sender_email AutoGPT <[email removed]>
ops_sender_email AutoGPT Platform <[email removed]>
postmark_transactional_stream outbound

4.4 Secrets reference (credentials)

All default to empty. Only set what you use.

Category Variables
Core ENCRYPTION_KEY, UNSUBSCRIBE_SECRET_KEY, RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS, VAPID_PRIVATE_KEY, VAPID_PUBLIC_KEY, VAPID_CLAIM_EMAIL
LLM providers OPENAI_API_KEY, OPENAI_INTERNAL_API_KEY, ANTHROPIC_API_KEY, GROQ_API_KEY, OPEN_ROUTER_API_KEY, LLAMA_API_KEY, AIML_API_KEY, V0_API_KEY, NVIDIA_API_KEY
OAuth apps GITHUB_*, GOOGLE_*, NOTION_*, TWITTER_*, DISCORD_*, REDDIT_*, LINEAR_*, TODOIST_* (_CLIENT_ID + _CLIENT_SECRET)
Email POSTMARK_SERVER_API_TOKEN, POSTMARK_WEBHOOK_TOKEN, SMTP_SERVER, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, MAILERLITE_API_TOKEN
Billing STRIPE_API_KEY, STRIPE_WEBHOOK_SECRET
Chat bots AUTOPILOT_BOT_DISCORD_TOKEN, AUTOPILOT_BOT_DISCORD_CLIENT_ID, AUTOPILOT_BOT_DISCORD_PERMISSIONS, AUTOPILOT_BOT_SLACK_TOKEN, AUTOPILOT_BOT_SLACK_SIGNING_SECRET, AUTOPILOT_BOT_SLACK_CLIENT_ID, AUTOPILOT_BOT_SLACK_CLIENT_SECRET, AUTOPILOT_BOT_TELEGRAM_TOKEN, AUTOPILOT_BOT_TELEGRAM_WEBHOOK_SECRET, AUTOPILOT_BOT_TELEGRAM_USERNAME, MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_TENANT_ID, DISCORD_BOT_TOKEN
Block providers REPLICATE_API_KEY, FAL_API_KEY, IDEOGRAM_API_KEY, DID_API_KEY, ELEVENLABS_API_KEY, UNREAL_SPEECH_API_KEY, E2B_API_KEY, EXA_API_KEY, JINA_API_KEY, MEM0_API_KEY, OPENWEATHERMAP_API_KEY, GOOGLE_MAPS_API_KEY, SCREENSHOTONE_API_KEY, MEDIUM_API_KEY, MEDIUM_AUTHOR_ID, APOLLO_API_KEY, SMARTLEAD_API_KEY, ZEROBOUNCE_API_KEY, ENRICHLAYER_API_KEY, AGENTMAIL_API_KEY, AYRSHARE_API_KEY, AYRSHARE_JWT_KEY, TALLY_API_KEY, WEBSHARE_PROXY_USERNAME, WEBSHARE_PROXY_PASSWORD
Observability & flags SENTRY_DSN, LAUNCH_DARKLY_SDK_KEY, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST (https://cloud.langfuse.com), LANGFUSE_TRACING_ENVIRONMENT (local), POSTHOG_API_KEY, POSTHOG_HOST (https://eu.i.posthog.com), POSTHOG_PERSONAL_API_KEY
Moderation AUTOMOD_API_KEY
Copilot feature requests COPILOT_LINEAR_API_KEY, LINEAR_FEATURE_REQUEST_PROJECT_ID, LINEAR_FEATURE_REQUEST_TEAM_ID

4.5 AutoPilot and memory settings

Variable Default Purpose
CHAT_USE_LOCAL false Route AutoPilot through an OpenAI-compatible endpoint
CHAT_USE_OPENROUTER appliance profile setting true → OpenRouter; false with ANTHROPIC_API_KEY → direct Anthropic
CHAT_BASE_URL empty e.g. http://host.docker.internal:11434/v1
CHAT_API_KEY empty Must be non-empty for local servers
CHAT_FAST_STANDARD_MODEL (and other CHAT_*_MODEL) — Bare model names for local backends
CHAT_DAILY_COST_LIMIT_MICRODOLLARS / CHAT_WEEKLY_COST_LIMIT_MICRODOLLARS -1 in the appliance Spend caps; HTTP 429 when exceeded
GRAPHITI_FALKORDB_HOST / _PORT / _PASSWORD localhost / 6380 / local-dev-password FalkorDB connection
GRAPHITI_LLM_MODEL gpt-4.1-mini Extraction LLM
GRAPHITI_EMBEDDER_MODEL text-embedding-3-small Embeddings
GRAPHITI_RERANKER_MODEL — Reranker
GRAPHITI_SEMAPHORE_LIMIT 5 Graphiti concurrency

Key fallbacks: Graphiti's LLM key falls back to CHAT_API_KEY, then OPEN_ROUTER_API_KEY, then (local) the chat config; its embedder key falls back to CHAT_OPENAI_API_KEY, then OPENAI_API_KEY, then (local) the chat config. Under CHAT_USE_LOCAL=true cloud-slug Graphiti defaults are rewritten to local-friendly slugs unless you set custom values.

Note

On the hosted cloud (BEHAVE_AS=cloud), CHAT_*_MODEL is the bottom layer of AutoPilot model resolution — the catalog routing cells in backend/data/llm_registry/catalog.py and the per-user LaunchDarkly copilot-model-routing flag take precedence. On self-hosted installs the catalog cells are skipped and the env vars are authoritative.

4.6 Frontend settings

Variable Default
BETTER_AUTH_SECRET blank → generated
BETTER_AUTH_URL http://localhost:3000
DATABASE_URL postgresql://postgres:...@localhost:5432/postgres
AUTH_DB_SCHEMA platform
AUTH_REQUIRE_EMAIL_VERIFICATION false
AUTH_ALLOW_NEW_ACCOUNTS / AUTH_SIGNUP_ALLOWLIST commented (open signup)
AUTH_GOOGLE_*, AUTH_GITHUB_*, AUTH_DISCORD_* commented (social sign-in)
SUPABASE_JWT_SECRET / SUPABASE_BRIDGE_MAX_TOKEN_AGE_DAYS commented / 30 (legacy session bridge)
NEXT_PUBLIC_AGPT_SERVER_URL http://localhost:8006/api
NEXT_PUBLIC_AGPT_WS_SERVER_URL ws://localhost:8001/ws
NEXT_PUBLIC_FRONTEND_BASE_URL http://localhost:3000
NEXT_PUBLIC_APP_ENV / NEXT_PUBLIC_BEHAVE_AS local / LOCAL
NEXT_PUBLIC_LAUNCHDARKLY_ENABLED false
NEXT_PUBLIC_TURNSTILE disabled
NEXT_PUBLIC_REACT_QUERY_DEVTOOL / NEXT_PUBLIC_TOKEN_DEVTOOL true
NEXT_PUBLIC_POSTHOG_KEY / NEXT_PUBLIC_POSTHOG_HOST empty / https://eu.i.posthog.com
NEXT_PUBLIC_GOOGLE_CLIENT_ID, NEXT_PUBLIC_GOOGLE_API_KEY, NEXT_PUBLIC_GOOGLE_APP_ID empty (Google Picker)
NEXT_PUBLIC_VAPID_PUBLIC_KEY dev key (replace with yours)
OPENAI_API_KEY empty (server-side transcription)

Warning

NEXT_PUBLIC_* values are compiled into the browser bundle. Never put a secret in a NEXT_PUBLIC_ variable.

4.7 Single-container appliance settings

Variable Purpose
AUTOGPT_PUBLIC_URL Exact browser origin (scheme + host + non-default port, no path)
AUTH_SIGNUP_ALLOWLIST, AUTH_ALLOW_NEW_ACCOUNTS, AUTH_REQUIRE_EMAIL_VERIFICATION Account policy
AUTOGPT_ENABLE_LEGACY_AUTH Keep false except for an intentional legacy symmetric-JWT migration
AUTOGPT_ENABLE_BOT_SERVICES true starts bot services and the linking manager
BEHAVE_AS local (default) or cloud
DB_CONNECTION_LIMIT / DB_CONNECT_TIMEOUT / DB_POOL_TIMEOUT 1–5 (5) / 1–600 (60) / 1–3600 (300)
POSTMARK_* Password reset and email-change messages
Provider keys, CHAT_*, GRAPHITI_* As in the backend

runtime_config.py validates the environment at boot and raises precise errors (see Troubleshooting). Generated secrets are written once to /data/config/runtime.env (root:root, 0600); supplying a different value later fails instead of silently rotating.

4.8 Migrations

Task Command
Apply (Compose) docker compose run --rm migrate
Apply (local dev) make migrate (prisma migrate deploy + prisma generate + gen-prisma-stub)
Create during development poetry run prisma migrate dev
Reset local DB make reset-db (deletes data/db/data)
Appliance Applied automatically on boot before readiness is published

Caution

Never stop the appliance during a boot-time migration, and never run an older image against a volume migrated by a newer one. Rollback = old image + its matching pre-upgrade backup restored into a new volume.

Notable migrations: 20260716120000_copy_supabase_users_to_better_auth copies Supabase auth.users into Better Auth tables during the Supabase → Better Auth upgrade.

Model retirement (catalog-as-code): set is_enabled: False in backend/data/llm_registry/catalog.py, then migrate existing graph nodes:

python -m backend.data.llm_registry.retire <slug> --replacement <slug> --yes

It is a dry run by default and revertable.


5. Deployment

5.1 Docker Compose (multi-container, from source)

git clone https://github.com/Significant-Gravitas/AutoGPT.git
cd AutoGPT/autogpt_platform
make init-env
docker compose up -d --build
✔ Container autogpt_platform-migrate-1       Exited
✔ Container autogpt_platform-rest_server-1   Started
✔ Container autogpt_platform-frontend-1      Started

Compose profiles:

Profile / target Use
default Full stack
deps service (make start-core) Postgres, Redis, RabbitMQ only — for running backend on the host
--profile local up deps_backend Backend dependencies for running the frontend on the host
--profile bot Adds platform_linking_manager for chat bots

Deployment checklist:

  • [ ] make init-env run; ENCRYPTION_KEY, UNSUBSCRIBE_SECRET_KEY, BETTER_AUTH_SECRET populated
  • [ ] DB_PASS, RABBITMQ_DEFAULT_*, VAPID keys replaced from published defaults
  • [ ] FRONTEND_BASE_URL, PLATFORM_BASE_URL, BACKEND_CORS_ALLOW_ORIGINS match real origins
  • [ ] JWT_JWKS_URL is HTTPS if backend and frontend are not on one host
  • [ ] OAuth apps registered with callback <frontend>/auth/integrations/oauth_callback
  • [ ] Only 3000 (and, if needed, 8006/8001) exposed through a TLS proxy; infrastructure ports not public
  • [ ] Backups scheduled for Postgres (and FalkorDB if memory matters)

5.2 Docker: single-container appliance

docker run --detach --name autogpt \
  --restart unless-stopped \
  --shm-size 2g \
  --ulimit nofile=65536:65536 \
  --log-driver json-file \
  --log-opt max-size=50m \
  --log-opt max-file=5 \
  --env-file autogpt.env \
  --publish 127.0.0.1:3000:3000 \
  --volume autogpt-data:/data \
  "${IMAGE}"

Internals:

  • Supervisor runs process groups; names are group-qualified (runtime:rest, state:postgres). supervisorctl status lists them.
  • Shutdown is tuned to fit Docker's stock 10-second timeout: runtime processes are signalled first; PostgreSQL, RabbitMQ, Valkey, and FalkorDB get at most five seconds each; the event listener stops last (measured ~8.4 s). Do not shorten Docker's timeout.
  • A watchdog allows 600 seconds for initial full health, then stops the container so --restart unless-stopped retries.
  • A fatal-event listener (fatal_listener.py) and probes (probe.py: HTTP, AMQP, Redis/cluster) back autogpt-healthcheck.
  • nginx and Next.js run under separate Unix identities; the frontend reaches PostgreSQL via a passwordless local peer role restricted to Better Auth tables/columns.

/data layout

Path Contents
/data/config runtime.env (generated secrets), backend.json
/data/postgres Auth and platform data
/data/rabbitmq Queue state (mnesia)
/data/valkey Three Valkey nodes (17000, 17001, 17002)
/data/falkordb Graphiti memory
/data/workspaces User workspaces
/data/store-media Marketplace media when GCS isn't configured
/data/home, /data/frontend-home Application homes
/data/cache Regenerable caches (excluded from backups)

Warning

Never mount one /data volume into two running containers, and never selectively mix service directories from different backups.

Optional processes: FalkorDB is mandatory. Chat-bot services default off; set AUTOGPT_ENABLE_BOT_SERVICES=true after configuring an adapter (Discord: AUTOPILOT_BOT_DISCORD_TOKEN; Telegram: token + webhook secret + a public HTTPS webhook).

Local models: on Docker Engine add --add-host host.docker.internal:host-gateway (Docker Desktop provides the hostname already).

5.3 Reverse Proxy / Load Balancing

Appliance. Keep the container bound to loopback and terminate TLS in a reverse proxy outside the container, forwarding to 127.0.0.1:3000; the appliance routes internally. Set AUTOGPT_PUBLIC_URL to the HTTPS origin:

AUTOGPT_PUBLIC_URL=https://agents.example.com

Example (nginx on the host):

server {
    listen 443 ssl;
    server_name agents.example.com;
    ssl_certificate     /etc/ssl/agents.crt;
    ssl_certificate_key /etc/ssl/agents.key;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Important

The bundled nginx records your proxy as the client. Your proxy must keep its own client-attribution logs and enforce per-client IP rate limits and access rules.

Caution

On Linux, Docker-managed port forwarding can bypass firewall rules expressed only through UFW. The 127.0.0.1: in --publish is the exposure control; publishing on a non-loopback address can expose the app regardless of INPUT-chain rules.

Compose. Route https://<host>/ → frontend :3000, and expose the backend API (:8006) and WebSocket (:8001) either on their own hostnames or paths, then set:

Setting Value
NEXT_PUBLIC_AGPT_SERVER_URL https://api.example.com/api
NEXT_PUBLIC_AGPT_WS_SERVER_URL wss://ws.example.com/ws
FRONTEND_BASE_URL / NEXT_PUBLIC_FRONTEND_BASE_URL / BETTER_AUTH_URL https://app.example.com
PLATFORM_BASE_URL https://api.example.com
BACKEND_CORS_ALLOW_ORIGINS ["https://app.example.com"]
JWT_JWKS_URL https://app.example.com/api/auth/jwks

Note

backend/api/utils/cors.py rejects localhost origins in production (Production environment cannot allow localhost origins), including via regex patterns.

Horizontal scaling: webhook-style chat adapters ride the N-replica REST deployment (no dedicated pod); socket adapters (Discord Gateway, Slack Socket Mode) run in a separate copilot-bot process. Executors scale by adding executor replicas consuming the same RabbitMQ queues; cluster locks live in Redis.


6. Security

6.1 Authentication

Layer Mechanism
End-user sign-in Better Auth embedded in the Next.js frontend (email/password; optional social providers via AUTH_*_CLIENT_ID/SECRET)
Backend request auth Asymmetric JWTs (ES256 by default) verified against JWT_JWKS_URL by autogpt_libs.auth
Legacy bridge Old Supabase JWT cookies are exchanged for a Better Auth session while SUPABASE_JWT_SECRET is set
API keys X-API-Key header, stored as APIKey rows with permissions (e.g. EXECUTE_GRAPH); validated by api/utils/api_key_auth.py
OAuth provider AutoGPT is itself an OAuth 2.0 authorization server (/api/oauth/token, /introspect, /revoke) with mandatory PKCE S256; tokens agpt_xt_... (1 h), refresh agpt_rt_... (30 d), codes (10 min)
Admin CLI for OAuth apps poetry run oauth-tool generate-app ...

Caution

The backend trusts whatever keys JWT_JWKS_URL returns. Over any untrusted network use HTTPS; a cleartext fetch lets an attacker substitute keys and forge tokens for any user. The backend refuses to boot with a cleartext non-local JWKS URL unless JWKS_ALLOW_INSECURE_TRANSPORT=true.

Account policy (appliance): allowlist by exact email or @domain; passwords ≥ 12 characters; AUTH_ALLOW_NEW_ACCOUNTS=false after bootstrap. Allowlisting compares the email asserted at signup — without email verification it is not proof of mailbox ownership.

6.2 Authorization & Access Control

Control Detail
Route guards Security(requires_user) / admin dependencies on FastAPI routers (e.g. presets router)
Admin role Granted by autogpt-admin promote (appliance); admin routers under /api/admin
API key permissions Per-route require_permission(APIKeyPermission.X) on the External API
OAuth scopes IDENTITY, EXECUTE_GRAPH, READ_GRAPH, WRITE_GRAPH, EXECUTE_BLOCK, READ_BLOCK, READ_STORE, WRITE_LIBRARY, USE_TOOLS, MANAGE_INTEGRATIONS, READ_INTEGRATIONS, DELETE_INTEGRATIONS
Org scoping Org-scoped API keys attribute executions to their org; team-restricted keys pin to that team
Entitlements BEHAVE_AS=cloud enforces subscription entitlements; local exempts every defined entitlement
Paywall enforce_payment_paywall() on execute routes (returns 503 on tier-lookup failure rather than failing open)
Marketplace Submissions require human review; listings are read-only in libraries until duplicated
Experts Per-expert credential allowlists (ExpertCredential) and spend approval thresholds

Warning

BEHAVE_AS=local also enables blocks disabled in hosted mode, self-host model routing, and different diagnostics/telemetry. Any multi-tenant deployment must use BEHAVE_AS=cloud — and even then the appliance frontend is compiled in local mode, so the appliance is not a turnkey multi-tenant distribution.

6.3 TLS / Certificates

  • AutoGPT does not terminate TLS itself; terminate at a reverse proxy.
  • For LAN splits, use locally trusted certificates (e.g. mkcert) and point JWT_JWKS_URL at the https:// URL.
  • Production OAuth redirect URIs must be HTTPS.
  • Telegram and Teams webhooks require public HTTPS endpoints.

6.4 Secrets handling

Secret Protection
Integration credentials Encrypted at rest with Fernet ENCRYPTION_KEY; injected into blocks at run time
.env.default files Must stay secret-free; enforced by .gitleaks.toml, detect-secrets, the check-env-defaults-blank pre-commit hook, and a unit test over BLANK_IN_ENV_DEFAULT
Appliance runtime secrets Generated on first boot into /data/config/runtime.env (0600, root)
Frontend process Receives only an allowlisted env: BETTER_AUTH_SECRET, AUTH_* client secrets, optional OPENAI_API_KEY, TRANSCRIPTION_API_KEY, legacy SUPABASE_JWT_SECRET — never the Postgres superuser, RabbitMQ/Valkey/FalkorDB passwords, or encryption keys
Templates / exports Store credential references only

Suspected exposure of appliance secrets: there is no in-place rotation. Isolate the installation, revoke external provider and OAuth credentials, build a new installation on a new volume, move only non-secret agent definitions via export/import, and reconnect credentials. Restoring an older backup does not rotate anything.

6.5 Input validation and network exposure

Risk Mitigation in source
SSRF from blocks backend.util.request.Requests validates URLs, resolves DNS, blocks private ranges (BLOCKED_IP_NETWORKS), disables redirects by default, supports trusted_origins
Malicious uploads ClamAV scanning (clamav_* settings; failed scans are not marked clean by default). The appliance has no antivirus — treat uploads as trusted input there
Content moderation Optional automod_* integration (fail-closed by default)
Browser caching of sensitive data SecurityHeadersMiddleware
CORS Production rejects localhost origins
Webhook forgery Providers with signatures override verify_signature using hmac.compare_digest (GitHub X-Hub-Signature-256, Airtable X-Airtable-Content-MAC, Slant3D HMAC-SHA256 with ms timestamp, Slack signing secret); unsigned providers rely on the unguessable webhook UUID
Teams bot Inbound Bot Framework JWT validated; serviceUrl claim bound to the token and outbound hosts allowlisted
Internal RPC Appliance binds AppService RPC to container loopback; Valkey requires auth
Shell tool Local bash_exec fallback relies on Bubblewrap user/network namespaces — do not make the appliance privileged to work around a host that disables them
Postgres config tampering Restore validation rejects non-loopback listen_addresses, include files, preload libraries, WAL archiving, and weakened pg_hba.conf

6.6 Security hardening checklist

  • [ ] Loopback-only publish + external TLS proxy
  • [ ] Signup allowlist during bootstrap, then AUTH_ALLOW_NEW_ACCOUNTS=false
  • [ ] No published defaults in use (DB_PASS, RabbitMQ creds, VAPID keypair, pre-v0.7.4 ENCRYPTION_KEY)
  • [ ] HTTPS JWT_JWKS_URL for any split deployment
  • [ ] BEHAVE_AS=cloud for anything multi-tenant
  • [ ] ClamAV enabled (Compose) or uploads restricted (appliance)
  • [ ] Unauthenticated local model servers not exposed to the internet
  • [ ] Backups encrypted (they contain plaintext secrets and user content)
  • [ ] Webhook URLs for unsigned providers treated as secrets

7. Operations

7.1 Start, stop, restart

Task Compose Appliance
Start docker compose up -d docker run ... (Quick start) or docker start autogpt
Stop docker compose down docker stop autogpt
Restart one role docker compose restart rest_server docker exec autogpt supervisorctl restart runtime:rest
Rebuild after upgrade git pull && docker compose up -d --build Replace container with new image (see Upgrade)
Status docker compose ps docker inspect --format '{{.State.Health.Status}}' autogpt

Note

Agent runs executing when services stop are abandoned: queue messages can be dropped and rows can stay RUNNING. They do not resume.

7.2 Upgrades

Compose:

  1. git pull the release.
  2. Diff each .env against its .env.default and copy new keys (make init-env won't merge them).
  3. docker compose build migrate rest_server && docker compose run --rm migrate.
  4. docker compose up -d --build.

Appliance:

  1. Record the running image reference and ID: docker inspect --format '{{.Config.Image}} {{.Image}}' autogpt.
  2. Pull/build the new image while the old one runs.
  3. export RESTART_AFTER_BACKUP=false, run the cold-backup block once, then unset RESTART_AFTER_BACKUP.
  4. docker rm autogpt (stopped container only).
  5. Re-run the original docker run with the new image reference.
  6. Wait for health; test login, memory, one agent execution, streaming, WebSockets, and persistence across one restart.

Secret-generation upgrade (installs from before per-install secrets): stop, export OLD_ENCRYPTION_KEY (for never-set keys it's the .env.default value at tag autogpt-platform-beta-v0.7.4), blank the three secret lines, make init-env, build + migrate, run cli rotate-encryption-key (dry run) then --apply, clear platform."UserAuthJwks" if BETTER_AUTH_SECRET changed, and start. Do the re-encryption before starting the stack on the new key.

Supabase → Better Auth upgrade: the database moves to pgvector/pgvector:pg15 at autogpt_platform/data/db/data; old data remains at autogpt_platform/db/docker/volumes/db/data. Either reuse the data directory (same major version; may fail on missing Supabase extensions/roles) or dump/restore with --no-owner --no-privileges, dropping the auth shim schema first. Users are copied by migration 20260716120000_copy_supabase_users_to_better_auth. frontend/scripts/migrate-supabase-auth.ts is only for live cutovers. Neither data path has been validated against a real old volume — back up first.

7.3 Logging

Where How
Compose docker compose logs -f <service>; make logs-core for core deps
Appliance docker logs --follow --tail 100 autogpt; json-file driver capped at 5 × 50 MB
Error tracking SENTRY_DSN
LLM tracing / prompts Langfuse (LANGFUSE_*); also manages the AutoPilot system prompt externally
Product analytics PostHog (POSTHOG_*)
Chat inspection poetry run cli chat list / cli chat view SESSION_ID [RANGE] --json

Log style (backend convention): %s deferred interpolation in debug, f-strings elsewhere; error messages use os.path.basename() to avoid leaking paths.

7.4 Monitoring & Health Checks

Endpoint / command What it proves
GET :8006/health REST server up and DB connected ({"status":"healthy"}; raises UnhealthyServiceError("Database is not connected") otherwise)
GET :8001/health (and /) WebSocket server up
Appliance GET /healthz nginx only — not whole-appliance readiness
docker exec autogpt autogpt-healthcheck Every bundled dependency and application role
Compose healthchecks rabbitmq-diagnostics -q ping, DB and Redis checks gate dependent services (service_healthy)
curl -s http://localhost:8006/health
{"status":"healthy"}

Built-in alerting (via configured Discord channels / notifications):

Signal Setting
Block error rate block_error_rate_threshold 0.5, checked every block_error_rate_check_interval_secs (24 h), top 3 blocks reported
Late executions Queued longer than execution_late_notification_threshold_secs (300 s) within a 1-hour window
Low balance low_balance_threshold (500)
Execution accuracy Every execution_accuracy_check_interval_hours (24)

Load testing: autogpt_platform/backend/load-tests/ (k6). Targets: core API P95 < 2 s, marketplace P95 < 5 s, success > 95 %.

cd autogpt_platform/backend/load-tests
node generate-tokens.js --count=160
node orchestrator/orchestrator.js DEV local

7.5 Backup & Restore

Compose. Back up PostgreSQL (and FalkorDB if you rely on memory) with service-native tools:

docker compose exec db pg_dump -U postgres -d postgres -Fc -f /tmp/autogpt.dump
docker compose cp db:/tmp/autogpt.dump ./autogpt.dump

Also preserve backend/.env — especially ENCRYPTION_KEY, without which restored credentials are unreadable.

Appliance cold backup. The documented block (in docs/platform/single-container.md):

  • refuses anonymous volumes and a stopped/crashed appliance;
  • takes an atomic lock (a stopped helper container named autogpt-backup-lock);
  • captures the exact image ID/digest, stops the appliance, and tars /data read-only with --network none, excluding ./cache;
  • writes autogpt-data-<UTC timestamp>.tgz plus .sha256, promoting from .partial only on success;
  • restarts the appliance unless RESTART_AFTER_BACKUP=false.

Caution

Backups are plaintext and contain user content, provider credentials, auth keys, and database passwords. Encrypt them and delete staging copies. Stale *.partial files from interrupted runs may also contain secrets. After a SIGKILL/host crash, confirm no backup is running, then remove a stale lock with docker rm --volumes autogpt-backup-lock.

There is no supported hot backup for the appliance's coupled volume.

Restore always goes into a new named volume (autogpt-data-restored-<ts>-<pid>-<random>), verifies the SHA-256, labels the volume with a per-run owner, extracts with --network none, then validates the layout offline (runtime.env, backend.json, PG_VERSION, Postgres configs, RabbitMQ mnesia, three Valkey dirs, FalkorDB, workspaces, store-media, homes) and rejects unsafe Postgres configuration. Only then launch with the recorded image, env file, publish spec, and optional ADD_HOST_SPEC.

Warning

tar runs as root during restore and preserves ownership and setuid bits. Only restore archives from a trusted backup process. A full recovery rehearsal boots live schedules and credentials — do it on an egress-filtered host after revoking production credentials.


8. Performance Tuning

Lever Setting Default Guidance
Graph worker concurrency num_graph_workers 10 Raise with CPU and DB headroom; add executor replicas to scale out
AutoPilot workers num_copilot_workers 5 Bounded also by per-user caps
Per-user graph cap max_concurrent_graph_executions_per_user 25 Protects shared capacity
AutoPilot per-user caps max_inflight_copilot_turns_per_user / max_running_copilot_turns_per_user 15 / 5
FastAPI threadpool fastapi_thread_pool_size 60 For sync handlers
DB pool DB_CONNECTION_LIMIT 12 (Compose), 5 max (appliance) Every role holds its own pool — total = roles × limit; stay under Postgres max_connections
DB timeouts DB_CONNECT_TIMEOUT / DB_POOL_TIMEOUT 60 / 300 Lowering pool timeout fails faster; it doesn't add capacity
LLM calls llm_request_timeout_seconds 600
RPC rpc_client_call_timeout, pyro_client_* 300, 15/100/30.0
Graphiti GRAPHITI_SEMAPHORE_LIMIT 5
ClamAV clamav_max_concurrency, clamav_service_timeout 10, 60
Uploads upload_file_size_limit_mb, max_file_size_mb 256, 100
Codex processes codex_max_active_processes 4 Bounded by --shm-size in the appliance

Tip

If requests stall under concurrent runs, inspect backend and PostgreSQL logs for pool exhaustion before changing limits. On the appliance, the fixed pools are the ceiling — move to a distributed deployment when they're insufficient.

Batch LLM work: the BatchExecutor polls submitted LLM batches (Anthropic) so slow batch polls never starve the scheduler's cron tick; the memory "dream pass" uses it when an Anthropic key is configured and falls back to a synchronous baseline otherwise.


9. Integrations

9.1 API Internals

The backend is one FastAPI app (backend/api/rest_api.py) with feature routers mounted under /api, the External API mounted as a sub-app at /external-api, and /health.

Router mount map (selected)

Prefix Feature
/api Graphs (/api/graphs...), executions, blocks, v1 features, experts, memory, home, desktop preview, trials
/api/library Library agents, folders, presets
/api/store Marketplace (profiles, agents, creators, submissions, media)
/api/store/skills Skill listings
/api/builder Builder helpers
/api/credits Credits and billing
/api/executions Admin execution analytics
/api/integrations Credentials, OAuth callbacks, webhook ingress (/generic_webhook/webhooks/{id}/ingress), providers
/api/api-keys API key management
/api/skills Skills
/api/copilot AutoPilot
/api/admin Admin routes
/api/review Human review (pending reviews)
/api/auth/email Auth email actions
/api/analytics, /api/experiments Analytics and experiments
/api/oauth/* OAuth provider (token, introspect, revoke)
/api/copilot-webhooks/teams/messages Teams bot messaging endpoint
/external-api/v1 Public External API

Graph routes (/api)

Method Path
GET /api/graphs
POST /api/graphs
GET /api/graphs/{graph_id}
PUT /api/graphs/{graph_id}
DELETE /api/graphs/{graph_id}
GET /api/graphs/{graph_id}/versions
GET /api/graphs/{graph_id}/versions/{version}
PUT /api/graphs/{graph_id}/versions/active
PATCH /api/graphs/{graph_id}/settings
POST /api/graphs/{graph_id}/execute/{graph_version}

Library routes (/api/library)

Method Path Handler
GET /agents list_library_agents
GET /agents/favorites list_favorite_library_agents
GET /agents/{library_agent_id} get_library_agent
GET /agents/by-graph/{graph_id} get_library_agent_by_graph_id
GET /agents/marketplace/{store_listing_version_id} get_library_agent_by_store_listing_version_id
POST /agents add_marketplace_agent_to_library
PATCH /agents/{library_agent_id} update_library_agent
DELETE /agents/{library_agent_id} delete_library_agent
POST /agents/{library_agent_id}/fork fork_library_agent
GET /agents/{library_agent_id}/triggers list_trigger_agents
GET /folders list_folders
GET /folders/tree get_folder_tree
GET /folders/{folder_id} get_folder
POST /folders create_folder
PATCH /folders/{folder_id} update_folder
POST /folders/{folder_id}/move move_folder
DELETE /folders/{folder_id} delete_folder
POST /folders/agents/bulk-move bulk_move_agents
GET /presets list_presets
GET /presets/{preset_id} get_preset
POST /presets create_preset
POST /presets/setup-trigger setup_trigger
PATCH /presets/{preset_id} update_preset
DELETE /presets/{preset_id} delete_preset
POST /presets/{preset_id}/execute execute_preset

External API v1 (/external-api/v1)

Method Path Permission / scope
GET /me IDENTITY
GET /blocks READ_BLOCK
POST /blocks/{block_id}/execute EXECUTE_BLOCK
POST /graphs WRITE_GRAPH + WRITE_LIBRARY
POST /graphs/{graph_id}/execute/{graph_version} EXECUTE_GRAPH — body {"node_input": {...}}, returns {"id": "<graph_exec_id>"}
GET /graphs/{graph_id}/executions/{graph_exec_id}/results READ_GRAPH — includes status; 404 if graph or execution missing
GET /store/agents Any valid auth (public data; auth required as anti-DDoS)
GET /store/agents/{username}/{agent_name} Any valid auth
GET /store/creators Any valid auth
GET /store/creators/{username} Any valid auth

Additional External API modules (external/v1/integrations.py, tools.py) expose integration management and platform tools under the same prefix; the Swagger UI at /external-api/docs is authoritative.

Export the OpenAPI schema:

cd autogpt_platform/backend
poetry run export-api-schema --output openapi.json --pretty

The frontend's typed client is generated with pnpm generate:api-client.

Error semantics: 400 bad parameters, 401 invalid/expired credentials, 403 missing scope/permission, 404 missing resource, 429 AutoPilot spend cap, 503 paywall tier-lookup failure on execute.

9.2 Webhooks

Inbound triggers. A webhook-triggered block declares webhook_config (BlockWebhookConfig), an event filter input (a Pydantic model of booleans whose field name matches webhook_config.event_filter_input), a payload input, and a credentials input with scopes sufficient to manage webhooks. A provider's WebhooksManager (subclass of BaseWebhooksManager in integrations/webhooks/_base.py) registers/deregisters webhooks with the provider and validates payloads; register it in load_webhook_managers in integrations/webhooks/__init__.py. Webhook records live in IntegrationWebhook.

Generic ingress URL:

https://<backend>/api/integrations/generic_webhook/webhooks/<webhook-id>/ingress

Important

Override verify_signature with hmac.compare_digest for any provider that signs deliveries and raise fastapi.HTTPException(403) on failure. For unsigned providers, the webhook UUID is a bearer secret — document that.

Stripe billing webhooks use STRIPE_WEBHOOK_SECRET; Postmark webhooks use POSTMARK_WEBHOOK_TOKEN.

Chat-bot webhooks. copilot/bot/ implements a connector taxonomy:

Adapter type Platforms Runs in
SocketAdapter Discord Gateway, Slack Socket Mode copilot-bot process (start/stop)
WebhookAdapter Slack Events API, Telegram, Microsoft Teams (WhatsApp next) Mounted on the main REST API via register_webhook_adapters

Factories: app.py::_build_socket_adapters, webhook_routes.py::_build_webhook_adapters — each gated on its tokens being set. Messaging: link check → Link Account prompt or thread creation → Redis-subscribed thread (7-day TTL) → streamed AutoPilot reply chunked at chunk_flush_at → messages arriving mid-stream batched into one follow-up turn.

Teams specifics: signed Bot Framework JWT (auth the sender, not the body — serviceurl claim binding closes replay); replies go to the activity's serviceUrl (host-allowlisted); single-tenant only (MICROSOFT_TENANT_ID mandatory since 2025-07-31); no native slash commands in channels (must @mention); group chats accepted and ignored; at-most-once delivery via a Redis activity-id claim; the learned serviceUrl map is per process. Local testing with the M365 Agents Playground requires both APP_ENV=local and AUTOPILOT_BOT_TEAMS_ALLOW_UNVERIFIED=true.

9.3 Plugin / Extension System: blocks

Blocks are the extension point. Every .py under backend/blocks/ is auto-imported at startup (except __init__.py and test_* files); no registration needed.

Block anatomy

Element Requirement
Class Subclass Block (backend.blocks._base or backend.sdk)
Input BlockSchemaInput with SchemaField(...) fields (advanced=True hides from basic UI; ge/le constraints)
Output BlockSchemaOutput (the error pin is predefined)
id A real uuid.uuid4() — never invented
categories BlockCategory values (e.g. SEARCH, AI, PRODUCTIVITY)
run() async def run(self, input_data, *, credentials=..., **kwargs) -> BlockOutput, yielding (name, value)
Tests test_input, test_output (values or types), test_mock, test_credentials

Runtime kwargs available to run(): user_id, graph_id, graph_exec_id, node_exec_id, node_id, execution_context (ExecutionContext: user_id, graph_exec_id, workspace_id, session_id — required for file handling).

Yield rules: prefer one result object at a time; for lists, yield each item and optionally the whole list. Yielding error stops the node and marks it failed; prefer raising.

Errors: raise BlockInputError (invalid input) or BlockExecutionError (user-addressable runtime failure) from backend.util.exceptions; bare ValueError is auto-wrapped. Don't wrap logic in blanket try/except, and don't catch infrastructure failures (out of credits, DB down, internal 5xx) — let them surface.

Files: store_media_file(file=..., execution_context=..., return_format=...):

return_format Returns Use
for_local_processing Local path ffmpeg, MoviePy, PIL
for_external_api Data URI Replicate, OpenAI
for_block_output workspace:// in AutoPilot, data URI in graphs Always for outputs

Credentials

Pattern How
API key only (recommended) Add ProviderName member → _auth.py (CredentialsMetaInput[Literal[ProviderName.X], Literal["api_key"]], a field factory, TEST_CREDENTIALS, TEST_CREDENTIALS_INPUT) → _config.py with ProviderBuilder(...).with_description(...).with_supported_auth_types("api_key").build()
SDK provider ProviderBuilder("x").with_api_key(ENV, title).with_base_cost(1, BlockCostType.RUN).build(); fields via provider.credentials_field()
OAuth2 OAuthHandler subclass of BaseOAuthHandler, added to HANDLERS_BY_NAME (integrations/oauth/__init__.py) and {provider}_client_id/secret in Secrets; or .with_oauth(Handler, scopes=..., client_id_env_var=..., client_secret_env_var=...)
Multiple credentials Field names end with _credentials and match run() parameter names
Other .with_user_password(), .with_webhook_manager()

Use credentials.auth_header() or credentials.api_key.get_secret_value() / credentials.access_token.get_secret_value(). Blocks that need OAuth with no API-key fallback should disable themselves when OAuth isn't configured (Google uses GOOGLE_OAUTH_IS_CONFIGURED).

Frontend: add frontend/public/integrations/{provider_name}.png (missing icon = broken image in the Blocks menu). Provider names, descriptions, and auth types are fetched from GET /integrations/providers — no frontend registration needed.

Networking: always use backend.util.request.Requests / backend.sdk.Requests (SSRF protection).

Docs sync (CI-enforced):

cd autogpt_platform/backend
poetry run python scripts/generate_block_docs.py

Writes docs/integrations/block-integrations/{provider}/{module}.md; the "Block Documentation Sync Check" workflow fails PRs whose docs drift. Preserve hand-written content between <!-- MANUAL: use_case --> … <!-- END MANUAL --> (sections how_it_works, use_case, extras, file_description, additional_content).

Integration checklist

  • [ ] Provider name registered (ProviderName or ProviderBuilder)
  • [ ] Credentials in _auth.py / SDK config; description + auth types in _config.py
  • [ ] Input/Output schemas, real UUID, categories, async run()
  • [ ] BlockInputError / BlockExecutionError for user-fixable errors
  • [ ] Inline tests and/or {name}_test.py
  • [ ] Icon PNG added
  • [ ] Block docs regenerated

Reference implementations: blocks/firecrawl/ (simple API key), blocks/linear/ (OAuth + API key), blocks/exa/ (webhooks), blocks/github/ (triggers + OAuth), blocks/zerobounce/ (_auth.py/_config.py pattern), blocks/typesafe/ and blocks/slant3d/ (documented provider packages).

9.4 LLM model catalog

Models, costs, and AutoPilot routing are catalog-as-code in backend/data/llm_registry/catalog.py. Block-selectable models also need a line in backend/data/llm_registry/llm_models.py (an import-time check enforces pairing). Catalog-only diffs may ship via hotfix/* → master.

9.5 MCP integrations

Hosted MCP services appear in Settings → Integrations with an MCP badge; catalog maintenance is documented in docs/platform/contributing/hosted-mcp-catalog.md. Open issue #15032 notes that AutoPilot's find_capability doesn't yet search user-connected custom MCP servers.


10. Developer Internals

10.1 Branching and contribution

Rule Detail
Main dev branch dev (all PRs target it)
Production master
Hotfix exception LLM-catalog-only diffs via hotfix/* → master
PR structure Why / What / How; one concern per PR; conventional commits
TDD Failing test first (@pytest.mark.xfail / Playwright .fixme), then fix, then remove marker

10.2 Backend code conventions (from backend/AGENTS.md)

  • Top-level, absolute imports (single-dot relative allowed within a package).
  • No duck typing for dispatch; Pydantic models over dicts/dataclasses.
  • No linter suppressors (# type: ignore, # noqa).
  • Files under ~300 lines; functions under ~40 lines; top-down ordering.
  • Security() (not Depends()) for auth dependencies so OpenAPI shows security.
  • Redis pipelines with transaction=True for multi-step atomicity; TOCTOU awareness for file access and credit charging; max(0, value) guards.
  • SSE: data: lines for parsed events (must match the frontend Zod schema), : comment lines for heartbeats.

10.3 Key classes

Class Module Role
AgentServer api/rest_api.py REST process
WebsocketServer api/ws_api.py WebSocket process
ExecutionManager, Scheduler executor/ Graph execution and scheduling
BatchExecutor executor/batch_executor.py LLM batch polling
DatabaseManager data/db_manager.py DB RPC service
NotificationManager notifications/notifications.py Email/push
PlatformLinkingManager platform_linking/manager.py Chat account linking
CoPilotExecutor / CoPilotChatBridge copilot/executor/manager.py / copilot/bot/app.py AutoPilot turns / chat bridge
SecurityHeadersMiddleware api/middleware/security.py Cache-protection headers
Block, BlockSchemaInput, BlockSchemaOutput, BlockWebhookConfig blocks/_base.py Block framework
ProviderBuilder sdk/ Provider registration
BaseOAuthHandler / BaseWebhooksManager integrations/oauth/base.py / integrations/webhooks/_base.py Extension interfaces
Config, Secrets util/settings.py Settings

10.4 Classic AutoGPT internals

Part Summary
forge/ Component-based agent framework: BaseAgent auto-discovers AgentComponent attributes; ConfigurableComponent[BM] for Pydantic-configured components; built-in components (file manager, action history, watchdog, system, archive handler, data processor)
original_autogpt/ CLI (autogpt run/serve/config) and Agent Protocol server (AP_SERVER_PORT, AP_SERVER_DB_URL, AP_SERVER_CORS_ALLOWED_ORIGINS)
direct_benchmark/ Benchmark harness (strategies, models, categories, external benchmarks gaia/swe-bench/agent-bench)
Config .env → .autogpt/autogpt.yaml → .autogpt/agents/{id}/permissions.yaml; SMART_LLM (gpt-4o), FAST_LLM (gpt-4o-mini), EMBEDDING_MODEL, DATABASE_STRING (sqlite:///agent.db), PORT (8000), FILE_STORAGE_BACKEND (local/s3/gcs), DISABLED_COMMANDS, RESTRICT_TO_WORKSPACE (True), TELEMETRY_OPT_IN
Permissions command_name(glob) patterns; {workspace}, **, *; agent deny → workspace deny → agent allow → workspace allow → prompt
URL safety forge/utils/url_validator.py blocks local files and private addresses

Caution

Classic has known vulnerabilities in its dependencies and will not be updated. Don't deploy it on a network-reachable host.

10.5 Testing Strategy

Layer Tooling Command
Backend unit/integration pytest, colocated *_test.py, snapshot tests poetry run test or poetry run pytest path::test -xvs
Snapshots pytest snapshot poetry run pytest path --snapshot-update (review diffs)
All blocks Inline block fixtures poetry run pytest backend/blocks/test/test_block.py -xvs
One block poetry run pytest 'backend/blocks/test/test_block.py::test_available_blocks[MyBlock]' -xvs
Block helper execute_block_test(block) In a *_test.py
Frontend pnpm test; Playwright E2E (PLAYWRIGHT_BASE_URL, PLAYWRIGHT_WORKERS, PLAYWRIGHT_RETRIES) pnpm test
Load k6 orchestrator (12 tests; local 5 VUs × 30 s, cloud 80–160 VUs × 3–6 min) node orchestrator/orchestrator.js DEV local
Appliance single-container/tests/ (incl. test_runtime_config.py enforcing blank secrets) pytest
AutoPilot quality Expert style eval poetry run expert-style-eval --dry-run / --write-baseline (paid, roughly $1–2 per expert)
Classic pytest poetry run pytest forge/tests/ etc.

Mocking rule: patch where a symbol is used (e.g. backend.blocks.my_provider.my_block.Requests.post), use AsyncMock for async. Block test files ending _test.py are auto-imported at startup — keep them side-effect-free, or name them test_*.py to opt out.


11. Troubleshooting

Boot and configuration

Error: ENCRYPTION_KEY is not set

Cause: Blank ENCRYPTION_KEY. Solution: make init-env, restart. Prevention: Include make init-env in provisioning.

Error: ENCRYPTION_KEY is set to a value that was published…

Cause: Pre-v0.7.4 default key. Solution: Run the secret-generation upgrade with OLD_ENCRYPTION_KEY and cli rotate-encryption-key --apply.

Error: ENCRYPTION_KEY is not set, so there is no key to re-encrypt under.

Cause: rotate-encryption-key run before a new key was set. Solution: Set the new ENCRYPTION_KEY first.

Error: --old-key is the configured ENCRYPTION_KEY. Change ENCRYPTION_KEY first, then pass the previous value here.

Solution: Put the new key in ENCRYPTION_KEY; pass the old one via --old-key/OLD_ENCRYPTION_KEY.

Error: Not a valid encryption key: ...

Solution: Generate a Fernet key: poetry run cli gen-encrypt-key.

Error: ENCRYPTION_KEY must be a Fernet-compatible key / must decode to exactly 32 bytes

Solution: Same — use a Fernet key, not an arbitrary string.

Error: JWT_JWKS_URL must be set to the JWKS endpoint of the platform auth service ...

Solution: Set JWT_JWKS_URL (e.g. http://frontend:3000/api/auth/jwks inside Compose).

Error: JWT_JWKS_URL fetches keys over cleartext http:// from a non-local host ('...')

Solution: Use HTTPS, or on a trusted isolated network set JWKS_ALLOW_INSECURE_TRANSPORT=true.

Error: Invalid JWT_JWKS_ALGORITHMS entry: '...'

Solution: Only asymmetric algorithms (ES256, RS256, EdDSA).

Error: 'cryptography' package is required for JWT verification but not installed

Solution: Reinstall backend dependencies (poetry install).

Error: Production environment cannot allow localhost origins

Also ... via regex: <pattern> and Production regex pattern matches localhost/127.0.0.1: <pattern>. Solution: Remove localhost entries from BACKEND_CORS_ALLOW_ORIGINS in production.

Error: <Class>.expected_token is not set; either specify it or provide a custom validator

Cause: An API-key-protected internal route has no expected token configured. Solution: Set the corresponding token (e.g. POSTMARK_WEBHOOK_TOKEN for Postmark webhooks).

Error: Database is not connected (HTTP 5xx from /health)

Cause: Postgres unreachable or wrong DATABASE_URL. Solution: Check db health and credentials; confirm migrate completed.

Error: the specified Containerfile or Dockerfile does not exist

Cause: Podman. Solution: Use Docker.

db unhealthy on Windows

Solution: Switch Docker Desktop to the WSL 2 engine.

Nobody can reach the backend after rotating BETTER_AUTH_SECRET

Solution: DELETE FROM platform."UserAuthJwks"; then restart; keys regenerate on next sign-in.

Credentials marked revoked after starting on a new key

Solution: Stop, run rotate-encryption-key --apply, restart; users who reconnected in between must reconnect older credentials.

Supabase data directory restart-loops on pgvector/pgvector:pg15

Solution: Use the dump/restore fallback; drop the auth shim schema before pg_restore; verify select count(*) from auth.users before migrating.

Frontend (outside Docker) can't authenticate

Cause: Next.js reads only .env. Solution: make init-env; ensure DATABASE_URL and BETTER_AUTH_SECRET are in frontend/.env.

Appliance runtime configuration

Error: AUTOGPT_PUBLIC_URL must use http or https

Siblings: must include a host, must not include credentials, must be an origin without path, query, or fragment, has an invalid port, has an invalid host. Solution: A bare origin.

Error: <NAME> differs from the value persisted on first boot; restore the original value or start with a new data volume

Solution: Remove the override; generated secrets cannot be rotated in place.

Error: runtime configuration has missing or unknown keys / unsupported runtime configuration version / invalid runtime configuration line N

Cause: /data/config/runtime.env was edited or is from an incompatible version. Solution: Don't edit runtime.env; restore it from backup or start a new volume.

Solution: Replace the symlink/special file with the original regular file.

Error: RABBITMQ_DEFAULT_USER may not use the built-in guest account / contains unsupported characters

Solution: Pick another username.

Error: <NAME> must be at least 32 URL-safe characters / invalid URL-safe base64 value

Solution: Provide a longer URL-safe value, or let the appliance generate it.

Error: VAPID_PRIVATE_KEY and VAPID_PUBLIC_KEY must be set together

Also VAPID_PRIVATE_KEY must decode to exactly 32 bytes, VAPID_PUBLIC_KEY must be an uncompressed P-256 public key, cryptography is required to generate VAPID keys. Solution: Generate a proper pair or set neither.

Startup rejects DB_CONNECTION_LIMIT / DB_CONNECT_TIMEOUT / DB_POOL_TIMEOUT

Solution: Ranges 1–5, 1–600, 1–3600.

Startup rejects legacy JWT secrets

Solution: Remove JWT_VERIFY_KEY and SUPABASE_JWT_SECRET on fresh installs; for legacy migration set AUTOGPT_ENABLE_LEGACY_AUTH=true and both to the same ≥32-character secret.

Startup stops because email verification is enabled

Solution: AUTH_REQUIRE_EMAIL_VERIFICATION=false (unsupported in the appliance).

Health probe errors: AMQP credentials are missing / AMQP connection failed

Solution: Check RabbitMQ state in /data/rabbitmq and logs for the state:rabbitmq process.

Health probe errors: Redis authentication failed / Redis cluster is not healthy / Redis did not return PONG / Redis closed the connection

Solution: Inspect Valkey process logs; confirm the three nodes (17000–17002) started; check disk space in /data/valkey.

Health probe error: HTTP <status> from <url>

Solution: The named internal HTTP service is failing; read its supervisor log.

Supervisor errors: Supervisor event payload is too large / ended unexpectedly / has an unsupported type / has an invalid payload length

Cause: The fatal-event listener received malformed events. Solution: Restart the container; if recurring, capture logs for an issue report.

Container stays starting / becomes unhealthy

Solution: docker exec autogpt autogpt-healthcheck, then the logs for the first failed service. The watchdog stops the container after 600 s.

OOM-killed during startup

Solution: More memory; the appliance needs more than 5–6 GiB.

Interrupted migration blocks startup

Solution: Empty install → discard volume; existing → restore backup. prisma migrate resolve only from a separate recovery environment after verifying the DB state.

Data missing after replacing the container

Solution: Reattach the original named volume (check with the /data mount inspect command).

Backup refuses to run

Messages: Refusing backup because /data uses an anonymous volume, ... another backup may be running or its lock is stale, ... the autogpt container is not running, Refusing to overwrite an existing backup. Solution: Use a named volume; clear a stale autogpt-backup-lock only after confirming no backup is running; start and verify health first.

Restore refuses to run

Messages: Backup checksum verification failed, Refusing to reuse existing volume, ... ownership cannot be verified. Solution: Use a trusted archive/checksum pair and a fresh volume name.

Runtime and capacity

Runs stuck in RUNNING after restart

Solution: Start new runs; abandoned runs never resume.

Requests stall under concurrent runs

Solution: Check for pool exhaustion; reduce concurrency or scale out (appliance pools are capped at 5).

Valkey or FalkorDB memory/disk keeps growing

Cause: No appliance-level ceiling or eviction. Solution: Monitor, back up, and move to a distributed deployment for growth.

/setup fails with httpx.ConnectError

Solution: Start platform_linking_manager (--profile bot).

Teams bot replies 404 for some tenants

Cause: Per-process serviceUrl map; a cold replica falls back to the default host. Solution: Keep replies reactive; persist the mapping in Redis before enabling proactive sends.

Teams bot drops a turn

Cause: At-most-once delivery (claim before processing). Solution: Ask the user to resend; release the claim on failure if you prefer retries over duplicates.

AutoPilot 401 / 429

Solution: 401 → set the transport's key (OPEN_ROUTER_API_KEY for the default route, OPENAI_API_KEY for memory); 429 → spend cap reached.

Local memory ingestion fails

Solution: Pull the embedding model; set GRAPHITI_LLM_MODEL, GRAPHITI_RERANKER_MODEL, GRAPHITI_EMBEDDER_MODEL to slugs your server serves.

ValueError: graph_exec #<id> not found for user #<user> (WebSocket subscribe)

Cause: Client subscribed to an execution it doesn't own or that doesn't exist. Solution: Verify the execution ID and user.

ValueError: Execution <id> not found

Solution: The execution was deleted or belongs to another user.

Schedule fires after its expert workflow was removed

Cause: Open issue #14607. Solution: Delete the schedule manually.

Development

Block shows a broken icon

Solution: Add frontend/public/integrations/{provider}.png.

CI "Block Documentation Sync Check" fails

Solution: poetry run python scripts/generate_block_docs.py, commit.

Block test fails with a type error on credentials

Cause: Missing CredentialsMetaInput[Literal[ProviderName.X], Literal["api_key"]] type hint. Solution: Add the full type hint.

Block module side effects run at startup

Cause: *_test.py files are auto-imported. Solution: Keep them side-effect-free or rename to test_*.py.

prisma generate writes to the global interpreter

Solution: pip uninstall prisma, rerun poetry run prisma generate.

OAuth tool: At least one scope is required / Invalid scope: ...

Solution: Pass --scopes with valid scope names (e.g. EXECUTE_GRAPH,READ_GRAPH).

CLI: Invalid --range '...'; use forms like '7', '6-10', '6-', '-10'. / start is after end

Solution: Fix the cli chat view range.

Load tests: No valid authentication token available / Token has expired

Solution: node generate-tokens.js --count=160 (24-hour tokens).

Load tests show 5 VUs in k6 cloud

Solution: k6 cloud run --env K6_ENVIRONMENT=DEV --env VUS=160 test.js.

Direct benchmark: Unknown benchmark: <name>. Available: ... / Workspace not initialized

Solution: Use gaia, swe-bench, or agent-bench; pass a valid --workspace.


12. Potential Improvements

Area Observation Suggestion
Scheduling correctness Issue #14607: a schedule survives removal of its workflow from an expert because execution doesn't check membership Validate expert-workflow membership at fire time; delete schedules on workflow removal
Block authoring Issue #15025: no scaffolder; block ID collisions are possible and the pairing of structural and dynamic tests is manual Add a generator that mints the UUID, checks collisions, and creates tests + docs stubs
AutoPilot discovery Issues #15032 / #14829: find_capability doesn't search user-connected custom MCP servers (skills search was a prior gap) Index connected MCP tools in the capability search
Appliance resource bounds Valkey and FalkorDB have no memory ceiling/eviction Ship default maxmemory policies and alerts
Appliance backup Cold backup only; coupled volume Offer per-service hot backup (e.g. pg_basebackup) for larger installs
Appliance secrets No in-place rotation of generated secrets Add a supported rotation command mirroring rotate-encryption-key
Appliance uploads No malware scanning Optional bundled ClamAV profile
Email verification Unsupported in the appliance Support required verification via Postmark
Appliance → distributed migration No in-place conversion; accounts, runs, schedules, credentials, memory aren't migrated Provide an export/import path for full state
Supabase upgrade Both data-migration routes are unvalidated against real old volumes Add an automated, tested migration tool
Teams bot At-most-once delivery; per-process serviceUrl map Persist mapping in Redis; configurable retry semantics
Published dev keys .env.default still ships a dev VAPID keypair and a RabbitMQ dev password Move them to BLANK_IN_ENV_DEFAULT and generate at init-env
Pool sizing Per-role pools multiply connections; appliance capped at 5 Add pgbouncer or a shared pool for the appliance
In-flight runs Abandoned on shutdown; rows remain RUNNING Reconcile orphaned executions on startup
Classic Unsupported with known vulnerable dependencies Archive into a separate repository or pin/scan dependencies
Hosted installer Not yet live; README points to the manual path Complete release gates for the appliance installer

13. Quick Reference

Paths

Item Path
Compose project autogpt_platform/
Backend env autogpt_platform/backend/.env
Frontend env autogpt_platform/frontend/.env
Postgres data (Compose) autogpt_platform/data/db/data
Old Supabase data autogpt_platform/db/docker/volumes/db/data
Blocks autogpt_platform/backend/backend/blocks/
Settings model autogpt_platform/backend/backend/util/settings.py
Prisma schema autogpt_platform/backend/schema.prisma
Model catalog autogpt_platform/backend/backend/data/llm_registry/catalog.py
Appliance secrets /data/config/runtime.env

Ports

Port Service
3000 Frontend / appliance nginx
8001 WebSocket
8002 Executor
8003 Scheduler
8005 Database manager
8006 REST API
8007 Notifications
8008 AutoPilot executor
8009 Platform linking manager
8010 / 8011 Chat bridge / batch executor (config defaults)
5432 PostgreSQL
5672 RabbitMQ
17000–17002 Redis cluster
6380 / 3001 FalkorDB / FalkorDB UI
3310 ClamAV

Commands

Task Command
Initialize env make init-env
Start stack docker compose up -d --build
Migrate docker compose run --rm migrate
Health curl http://localhost:8006/health
New encryption key poetry run cli gen-encrypt-key
Rotate key docker compose run --rm --no-deps -e OLD_ENCRYPTION_KEY rest_server cli rotate-encryption-key --apply
Reset JWKS docker compose exec db psql -U postgres -c 'DELETE FROM platform."UserAuthJwks";'
Register OAuth app poetry run oauth-tool generate-app --name ... --redirect-uris ... --scopes ...
Export OpenAPI poetry run export-api-schema --output openapi.json --pretty
Test all blocks poetry run pytest backend/blocks/test/test_block.py -xvs
Regenerate block docs poetry run python scripts/generate_block_docs.py
Appliance admin docker exec autogpt autogpt-admin promote EMAIL
Appliance health docker exec autogpt autogpt-healthcheck
Appliance processes docker exec autogpt supervisorctl status

Critical settings

Setting Value
ENCRYPTION_KEY Generated Fernet key — back it up
JWT_JWKS_URL https://<frontend>/api/auth/jwks when split
BEHAVE_AS local single-tenant / cloud multi-tenant
AUTOGPT_PUBLIC_URL Exact browser origin
AUTH_ALLOW_NEW_ACCOUNTS false after bootstrap
DB_CONNECTION_LIMIT ≤ 5 on the appliance