aegra is a self-hosted agent backend whose default configuration has authentication switched off
Open source alternative to LangGraph Platform (now LangSmith Deployments) - Self-hosted AI agent backend with FastAPI and PostgreSQL. Zero vendor lock-in, full control over your agent infrastructure.
At a glance
- What is it?
- An alternative to a hosted agent platform that keeps the same SDK and talks to the same front ends, with Redis workers, scheduled jobs, streaming in two protocol versions and your own Postgres. The engineering is careful and unusually honest about its own tooling. The configuration file is the part to read first: no auth, every interface, and a placeholder database password.
- Who is it for?
- aegra fits a team that has outgrown a hosted agent platform and wants the same SDK against infrastructure it controls, and it does not fit anyone who wants a deploy with no decisions in it. Three things to settle first.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The package named aegra is the one the file tells you not to install
There are three packages on the index and a note that singles out one of them.
The quick start opens with the install line, and the whole path is four commands after it:
pip install aegra-cli
# Initialize a new project — prompts for location, template, and name
aegra init
# Follow the printed next steps:
cd <your-project>
cp .env.example .env # Add your OPENAI_API_KEY to .env
uv sync # Install dependencies
uv run aegra dev # Start PostgreSQL + dev serverThe server package and the command line package are separate distributions, and both are linked from the top of the file. A third package exists simply to pull the others in, and the note says plainly that you should always install the command line package directly rather than the wrapper, because the wrapper is a convenience and does not support version pinning.
That is a real trap rather than a formality. A project named aegra whose obvious install command is the name of the wrapper is the path most people take first, and the consequence of that path is that your environment's contents move whenever someone publishes.
The repository is organised to match. The root project file is a workspace whose own version is a placeholder zero and which declares itself as not being a distributable package, with member packages discovered from a single directory. So the two real packages live side by side under that directory, and the root exists to configure the tooling rather than to be installed.
The Python floor is 3.12 or newer, and the toolchain is uv rather than a plain virtual environment, which is why the quick start tells you to sync and then run through it.
The shipped configuration has no authentication and listens on every interface
The example environment file is the most useful page in the project and the one to read before anything else.
It sets the authentication type to a value whose name says what it does, with a comment listing the available choices as noop and custom. The feature list separately offers JWT, OAuth, Firebase or none as the authentication options, implemented as Python handlers. So a fresh install has no authentication at all, and adding it is a deliberate act.
Then the server settings: the host is set to all interfaces and the port to 2026. A comment explains that a server URL setting takes precedence over host and port when set, and that when it is unset it is derived automatically from the host and port values.
Put those two blocks together and the default is an unauthenticated agent backend reachable on every address the machine has. That is a reasonable default for a laptop and a bad one for a host, and nothing in the file stops the combination.
The derived URL is worth a second look as well. With the host set to a bind address rather than a name, an automatically derived URL contains that bind address, and anything that builds absolute links from it, such as a redirect target or a callback, inherits the odd value.
There is a session lifetime setting with a documented range, and a comment on the secure cookie flag saying it can be turned off for local development over plain HTTP, so the file has thought about the deployment cases.
The comparison is a tier matrix dated February 2026, and the product has two names
The table setting this project against the hosted platform is the marketing centre of the file, and it needs reading carefully.
First, the basis. A note above the table says it is based on the competitor's published pricing as of February 2026, and adds that an enterprise tier with self-hosting is available at custom pricing. So the entire comparison is pinned to a pricing page that was eight months old when this snapshot was taken, and prices change.
Second, the structure. Every claim about a missing capability is scoped to a paid tier. Deploying agents is described as local development only on the free tier and a paid cloud tier above it. Custom authentication and scheduled jobs are described as unavailable on the free tier and available on the paid one. Self-hosting is described as an enterprise feature requiring a licence key. What the own database row says is that the free and paid tiers are managed and the enterprise tier brings its own.
So the left column is a tier matrix rather than a product description, and the row that genuinely compares products is the SDK row, where both sides use the same SDK.
Third, the names. The repository description calls this an alternative to the platform's former name and notes it has been renamed. The page's own heading calls it an alternative to the current name, and the opening line calls it a drop in replacement for it. Both names appear in the same file, which is harmless and a small signal that the rename is recent.
Thirty concurrent runs per instance is two environment variables multiplied
The feature list advertises a worker architecture with a Redis job queue, thirty concurrent runs per instance, lease based crash recovery, and horizontal scaling across instances.
The compose file shows how that number is reached. It sets a worker count of three and a jobs per worker value of ten, and three times ten is the thirty in the feature list. So the concurrency limit is two ordinary environment variables, and the advertised figure is one particular deployment's default rather than a property of the system.
Redis is what makes the rest true. It is the broker, it is enabled by an environment flag, and it is what carries the pub/sub that lets a stream opened on one instance be followed from another. Lease based recovery is what makes a crashed worker's jobs return to the queue rather than vanish.
Scheduled jobs use the same machinery. Cron triggers accept standard five field expressions or six field expressions with seconds, with IANA timezone support, and the claim is described as safe across multiple instances using a database-level skip locked pattern, which is how two replicas avoid taking the same due job.
One detail from the compose file to keep in mind: both the database and Redis publish ports to the host, so the two backing services are reachable from outside the compose network by default.
The production compose file runs the server with reload turned on
The compose file that looks like the deployment one ends up running a development server.
The server command is the ASGI server with the host set to all interfaces and, more to the point, the reload flag enabled, inside a service that also declares a restart policy of unless stopped and a health check that curls the health endpoint every thirty seconds with a start period.
There is a separate compose file for development and a third for the authentication path, so the arrangement is deliberate: the default file is the one people run first. Which means the first thing most users get is a server that watches the filesystem and restarts on change, mounted in a way that makes that expensive. The reload flag is the signal, and it is the one line to change first when this file is used for a real deployment.
The mounts explain why. The configuration file, the examples directory, the server source and the migrations directory are all mounted read only from the host into the container, which is what lets a local edit change the running server without a rebuild. That is the right shape for development and the wrong shape for production, and the reload flag is the tell.
The health check is worth copying if you deploy it yourself: it probes the health endpoint rather than the API root, and the database and Redis services both gate the server on their own health checks passing first.
Two connection pools against one database, and three ways to spell its URL
The database section of the configuration file is more instructive than it looks.
There are three documented ways to point the system at Postgres. The first is a single connection string, with a warning that if the password contains characters like the at sign, slash, hash, percent or plus, they must be URL encoded, and an example. The second is a multi host form for native Postgres high availability, where failover is handled by the driver. The third is a set of individual fields, used when the connection string is not set at all.
The shipped example uses the third option, with a placeholder password and a host of loopback, which is the right default for a local run and one more value to change before anything else.
Then the pools. There are two, configured separately: one for the metadata and application database work, with a size of ten and an overflow allowance of twenty, and one for the agent runtime, with a minimum of five and a maximum of twenty. So the total number of connections is the sum of both, and the database's own connection limit is the ceiling you are working against without being told.
Two pools rather than one is the right call when the runtime load pattern differs from the application one, since a long running agent should not be able to starve the metadata queries the interface depends on.
Two streaming protocols, and the documentation counts them differently
Streaming is the feature the file leads with, marked as new, and it has two faces.
The new one is the second version of the agent protocol, described as thread scoped server sent events with content block events, per subgraph lifecycle information, and native resumption of a human in the loop pause. The callout says it is enabled by default and is the wire the recent LangGraph clients target.
The older one is run scoped, and the feature list says both are supported. That matters during an upgrade: a client pinned to the older SDK keeps working while a newer client gets the newer protocol, and the switch is described as being on by default rather than negotiated per request.
The documentation index gives a third number. The streaming row in the docs table says there are eight stream modes with reconnection, which is a different count from the two protocols in the feature list and a finer one, since modes and protocols are not the same axis. Automatic reconnection with event replay is the feature that separates them from plain streaming, and it depends on the pub/sub layer, which is why the broker appears in the compose file.
The same two-version pattern shows up in the examples. Of the eleven example entries in the repository, two are specifically human in the loop variants and two are subgraph variants, which suggests those two paths are the ones the author found hardest and therefore the ones worth demonstrating.
Markdown formatting is disabled on purpose, and the CLI table is missing a command
The tooling configuration contains one line that is worth reading out loud.
The formatter is configured to skip markdown files, and the comment explains why: the documentation contains deliberately wrong examples, marked as such in the agent instruction file, and formatting markdown would rewrite them into correct style and destroy the point. The note even records that the formatter only began including markdown in a recent version and that this keeps the earlier behaviour.
That is a small piece of engineering culture in one setting. A project that keeps broken examples broken, on purpose, because the breakage is the lesson, has thought about what its documentation is for.
The rest of the tooling is a replacement rather than an addition. A newer standalone type checker has taken over from the older one, with its own rule configuration instead of strictness flags, and the line length is set to 120 with a target of Python 3.12. The Makefile exposes security checks through a separate tool, an OpenAPI regeneration target that rewrites the schema document from the code, and four end to end modes: development without Redis, production with Redis workers, the authentication path with mock authentication enabled, and both.
One inconsistency to be aware of. The configuration file tells you that in a multi replica deployment you should turn off automatic startup migrations and run a database upgrade command out of band instead. The command list in the file covers initialise, develop, serve, bring the stack up, bring it down and version. The upgrade command is not in that list.
Editorial conclusion
aegra fits a team that has outgrown a hosted agent platform and wants the same SDK against infrastructure it controls, and it does not fit anyone who wants a deploy with no decisions in it. Three things to settle first. Turn authentication on before the server is reachable from anywhere, because the example configuration ships with it disabled and with the server bound to every interface. Install the command line package directly rather than the convenience wrapper, since the wrapper is what the file tells you not to use because it cannot be pinned. And read the migration setting if you run more than one replica, because the automatic startup migration is explicitly not for that case and there is a separate upgrade command that the file's own command list never mentions.
Frequently asked questions
How do I install aegra?
Install the command line package directly with pip, then run aegra init to create a project, copy the example environment file to your own, add your OpenAI key, sync the dependencies with uv and run the development command, which starts PostgreSQL and a server. You need Python 3.12 or newer and Docker. Do not install the aegra wrapper package, which the file says cannot be version pinned.
Is aegra a drop-in replacement for LangSmith Deployments?
The file describes it that way: the same LangGraph SDK and the same APIs, with PostgreSQL persistence instead of a hosted platform. It lists Agent Chat UI, LangGraph Studio and the AG-UI and CopilotKit integrations as compatible front ends, and the local API reference is served from a documentation path on port 2026.
Does aegra have authentication enabled by default?
No. The example environment file sets the authentication type to a value that disables it, and lists noop and custom as the type options, with JWT, OAuth and Firebase available as handlers. The same file sets the host to all interfaces, so the default configuration is an unauthenticated server on every address.
What database does aegra need?
PostgreSQL with the vector extension, since the compose file uses a vector-enabled image. You can supply a single connection string, a multi-host form for native high availability with driver-handled failover, or individual fields, which is what the example uses. If you use the string form and the password contains an at sign, slash, hash, percent or plus, those characters must be URL encoded.
How does aegra run scheduled agent jobs?
With built-in cron triggers that accept standard five field expressions or six field expressions including seconds, with IANA timezone support. The claim across instances is described as safe through a skip locked pattern, so two replicas do not take the same due job. The jobs run on the same Redis backed worker pool as everything else.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/aegra-aegra)