To self-host LangGraph agents on Control Plane, create a dictionary secret with the database username, password and database name, then install the Aegra template from the Template Catalog, Control Plane’s library of ready-to-install apps. You get an Aegra agent server running your graphs, a bundled PostgreSQL with pgvector, a Redis job queue, and an API that stays closed to the internet until you open it.
Your agent graph works in a notebook. Now a teammate wants to call it from an app, a run takes twenty minutes, and the frontend wants to stream tokens. Aegra is an Apache 2.0 agent server that implements the LangGraph Agent Server API, so the LangGraph SDK and Agent Chat UI talk to it as they would to LangChain’s hosted server, and its repository has more than 1,300 GitHub stars. It gives your graphs assistants, threads, background runs, streaming, a store and crons. Around it you still need PostgreSQL with pgvector, Redis, a place for model keys and a decision about who can reach the endpoint. The template brings all of it up together.
Why self-host LangGraph agents on Control Plane
-
Your graphs, your image. Build from the Aegra image with your code and an
aegra.json, then setaegra.image. - State in a database you own. Threads, runs, checkpoints and the store live in a bundled PostgreSQL with pgvector, on a volume set, Control Plane’s managed persistent storage for a workload.
-
Model keys by reference. Keys such as
OPENAI_API_KEYsit in a Control Plane dictionary secret, a secret that holds named key-value pairs, and become environment variables inside the container. They never appear in Helm values. -
Permissions that stop at your secrets. A Control Plane policy grants the workload’s identity
revealon exactly the secrets you name, and the template creates no credentials of its own. - Closed until you open it. No public URL by default; workloads in the same Global Virtual Cloud (GVC), Control Plane’s term for the set of locations a workload runs in, use internal DNS.
- Scale by replica count. Up to ten interchangeable replicas share the same database and job queue.
Included out of the box
- Aegra 0.11.0 (a community build) serving the API on port 2026, with interactive OpenAPI docs at
/docs - PostgreSQL 18 with pgvector 0.8.7 on a 10 GiB volume
- A single-node Redis for the job queue and run event streams
- Aegra’s example graphs:
stress_testneeds no model key,agentneedsOPENAI_API_KEY - Optional Langfuse tracing of every run
- Optional scheduled database backups to Amazon S3, Google Cloud Storage or MinIO
- Built-in Control Plane logs and metrics, with tracing available to turn on
How to run your own LangGraph agent on Aegra
Build an image FROM upstreamyard/aegra:0.11.0 with your code, its requirements, an aegra.json that maps graph names to files ("my_agent": "./my_agent/graph.py:graph") and AEGRA_CONFIG pointing at it. The cpln CLI, Control Plane’s command-line tool, builds and pushes it to your org’s registry with cpln image build --name my-agent:1 --dockerfile Dockerfile --push; then set aegra.image to ORG_NAME.registry.cpln.io/my-agent:1. Your image serves only your graphs: point the LangGraph SDK’s get_client(url=...) at the server and pass a graph’s aegra.json name as the assistant id.
How to keep the Aegra API private
Aegra has no authentication unless your image configures an auth handler in aegra.json. Without one, anyone who can reach the URL can run your agents and read every thread, so publicAccess.enabled defaults to false.
From your machine, cpln port-forward RELEASE_NAME-aegra 2026:2026 --gvc GVC_NAME gives you http://localhost:2026. Other workloads in the GVC call http://RELEASE_NAME-aegra.GVC_NAME.cpln.local:2026 over mTLS. Set internalAccess.type to same-org, workload-list (named workloads only) or none to change who counts as inside.
Before you publish, add an auth handler (JWT, OAuth, Firebase or your own Python function) with its signing secret in your agent secrets. The handler must raise to reject a request: returning any user, a guest included, lets it in.
The bundled Redis has no password by default and accepts any workload in the GVC. To require one, put a URL-safe password key in a dictionary secret and set redis.redis.auth.fromSecret.enabled: true with its name.
How Aegra recovers a run when a replica restarts
Replicas share PostgreSQL and Redis, so any of them can pick up work. When a replica crashes or hangs, its 30-second lease on the run expires and a live replica, or the restarted one, resumes the run from its last checkpoint, up to 3 retries by default. Aegra 0.11.0 does not drain runs on shutdown, so a rolling update or restart cuts in-flight runs, and each one is retried the same way, using one of its retries.
If the database is unreachable for more than 30 seconds, for example during a PostgreSQL failover, a run ends in error and you submit it again. The public URL cuts /runs/wait and /runs/stream requests after aegra.requestTimeoutSeconds (600 by default, up to 3600). Calls over cpln.local inside the GVC are not subject to it.
How to back up Aegra
All state lives in PostgreSQL. Backups are off by default. Set postgres.backup.enabled: true (or postgresHA.backup.enabled: true with the HA database) and fill in the aws, gcp or minio block, and a job writes a compressed pg_dumpall to your bucket daily at 02:00 UTC. AWS and GCP need a bucket and a Control Plane cloud account (plus a bucket-scoped IAM policy on AWS). MinIO or any S3-compatible endpoint needs a dictionary secret with accessKey and secretKey.
To restore, replay the dump into an empty database as the PostgreSQL template documentation describes. Its S3 and MinIO paths are tested end to end and its GCS path is not, so rehearse a restore first.
Uninstalling deletes the database volume, and every thread with it. Control Plane keeps a final snapshot of that volume for 7 days, which covers an accidental uninstall; the bucket is the real backup.
How to scale Aegra and turn on high availability
The default is one Aegra replica, one PostgreSQL server and one Redis node, in a GVC with exactly one location, because the bundled database and Redis run in one location. Raise aegra.replicas up to 10 to spread background runs; the count is fixed, and each replica handles up to 30 concurrent runs by Aegra’s defaults. For database failover and fewer interruptions during upgrades, install with aegra.replicas: 2, postgres.enabled: false, postgresHA.enabled: true and postgresHA.config.credentialsSecretName set to your database secret. That swaps the single server for a three-member Patroni PostgreSQL 17 cluster, three etcd members and an HAProxy endpoint that follows the leader. Redis stays a single node because Aegra takes one Redis URL and cannot follow Sentinel; runs are recovered from PostgreSQL if Redis restarts.
How to trace agent runs with Langfuse
Set langfuse.secretName to a dictionary secret holding publicKey and secretKey, plus langfuse.baseUrl, and every run reports its trace to a Langfuse release or Langfuse Cloud. If Langfuse sits in another GVC, set its internalAccess to same-org. Aegra ships no UI. The hosted Agent Chat UI takes your server URL and a graph name, but the browser calls Aegra directly, so it needs the public URL and an auth handler.
How to deploy Aegra on Control Plane
Sign up for Control Plane and create the database credentials secret. Secret names are org-wide, so give each release its own:
cpln secret create-dictionary --name DB_CREDENTIALS_SECRET_NAME \
--entry username=aegra \
--entry password="$(openssl rand -hex 32)" \
--entry database=aegra
Then pick Aegra in the Template Catalog in the Control Plane Console, or install the default image with the CLI:
cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/aegra \
--version 1.0.0 --gvc GVC_NAME \
--set postgres.config.credentialsSecretName=DB_CREDENTIALS_SECRET_NAME
If a named secret is missing, the deployment waits with empty cpln logs; create the secret and run cpln workload force-redeployment RELEASE_NAME-aegra --gvc GVC_NAME. The Aegra template documentation covers custom images, backups and troubleshooting.
FAQ
Answers to common questions about running Aegra and LangGraph agents on Control Plane.
How do I self-host LangGraph agents?
Run them on Aegra, an open-source server for the LangGraph Agent Server API. On Control Plane, create the database secret, install the Aegra template, and set aegra.image to an image with your graphs.
Is Aegra free to self-host?
Yes. Aegra is Apache 2.0 licensed. On Control Plane you pay for the CPU and memory that the Aegra, PostgreSQL and Redis workloads reserve.
Does Aegra have authentication?
Only if your image adds an auth handler in aegra.json. Without one, anyone who can reach the URL can run your agents and read every thread, so the template keeps the public URL off.
How do I back up Aegra?
Back up its PostgreSQL database. Set postgres.backup.enabled: true to write a daily pg_dumpall to Amazon S3, Google Cloud Storage or MinIO. Backups are off by default.
What happens to a running agent if an Aegra replica crashes?
A live replica, or the restarted one, picks it up. Once the 30-second lease expires, the run resumes from its last checkpoint, up to 3 retries by default.
Can I run Aegra on Kubernetes?
Yes, without operating a cluster: Control Plane runs the workloads for you. It can also run them on a Kubernetes cluster you already operate through bring your own Kubernetes (BYOK).
Does Aegra on Control Plane scale?
Yes. Run up to 10 replicas that share one database and job queue, each handling up to 30 concurrent runs by default.
Can Aegra run in more than one location?
Not with this template. Use a GVC with one location, because the bundled PostgreSQL and Redis run in one. The optional HA database adds failover inside that location.
Originally published on the Control Plane blog.
Top comments (0)