fix: address RC2 vote feedback (#745)
* fix: add __init__.py to tests/ so pytest discovery works
* fix: add ASF license header to tutorial.md
* fix: update .rat-excludes for RC2 feedback
- Fix patterns for burr/examples/ symlink duplicates (use .* prefix)
- Add .github/ templates (YAML/MD with frontmatter)
- Add image file extensions (.png, .gif, .ico, .jpg)
* fix: include hello-world-counter in release artifacts
The tracking server imports burr.examples.hello-world-counter.server
(added in #675) but the release config still had it in the exclude
list. Move it from exclude to include so the wheel ships with the
module the server needs, preventing ModuleNotFoundError when running
burr from a fresh install.
Also bumps REQUIRED_EXAMPLES in scripts/apache_release.py and updates
tests/test_release_config.py accordingly.
* fix: use sys.executable for uvicorn subprocess to fix venv isolation
The CLI spawned uvicorn as a bare command, which resolves via PATH.
For users with pyenv installed, ~/.pyenv/shims/ is in PATH ahead of
any venv's bin/, so bare `uvicorn` always hits a pyenv shim that
routes to a pyenv environment β never the venv the user is running
burr from. This means a fresh `pip install` into a non-pyenv venv
fails to start the server.
Using sys.executable -m uvicorn ensures uvicorn runs under the same
Python interpreter that is running burr, regardless of PATH.
* chore: add --skip-signing flag and CI smoke-test helper
Preparation for the release-validation CI workflow.
apache_release.py:
- Add --skip-signing to archive/sdist/wheel/all subcommands
- Split _sign_artifact into checksum (always) and GPG sign (skippable)
- Drop gpg from required tools when --skip-signing is set
ci_smoke_server.py:
- Installs a built wheel into a fresh venv outside the source tree
- Imports burr.tracking.server.run (catches missing-example bugs like #675)
- Starts the burr server on a free port with a dedicated data dir
- Runs a tracked app, verifies the server observes the project
* ci: drop svn requirement from 'all' command when --no-upload is set
CI runners don't have svn installed. The 'all' subcommand listed svn as
a required tool unconditionally, but svn is only used during the upload
step. Skip the requirement when --no-upload is passed.
* ci: add release validation workflow
Build the full release pipeline on every PR, plus RAT license check
and an end-to-end smoke install of the wheel outside the source tree.
This catches the failure modes that have broken recent RCs:
- build-artifacts: runs apache_release.py all --skip-signing --no-upload,
verifies the 3 artifacts exist, runs Apache RAT without --report-only
so license violations fail the job.
- install-and-smoke: on 3.10/3.11/3.12, installs the wheel into a fresh
venv and runs scripts/ci_smoke_server.py. That helper imports the
server module, boots the server, runs a tracked app, and asserts the
server sees the project β so a missing example (like PR #675's
hello-world-counter) would fail here.
Only "build-artifacts" and "install-and-smoke (3.12)" are required
checks in .asf.yaml; 3.10 and 3.11 are informational.
* fix: rewrite .rat-excludes with basename patterns that actually work
RAT's -E regex doesn't reliably match through path separators or
symlinked directories. The previous patterns like
'examples/deep-researcher/prompts.py' never excluded anything because
RAT effectively matches against basenames. We never noticed because
all prior RAT runs used --report-only mode.
Switch to basename patterns. The .tsx files are uniquely named, so
basename matching is precise. prompts.py only exists once. utils.py
matches 5 different files (all our own ASF code with headers); the
practical risk of skipping their checks is low.
Update the leading comment in .rat-excludes to document the constraint
so future authors don't repeat the mistake.
* chore: add .claude/ to .gitignore
* fix: address review feedback (paths-ignore, basename collisions, count)
- Workflow: drop '**/*.md' from paths-ignore. It would suppress runs
whenever a bundled .md file (like the deployment tutorial.md) changes
β exactly the case that triggered RC2 feedback.
- .rat-excludes: document the basename collisions for utils.py and
button.tsx so the next maintainer doesn't think they're unique.
- test_release_config.py: fix '4 examples' string that should have been
bumped to 5 when hello-world-counter was added.
* fix: use os.path.lexists in _prepare_wheel_contents to handle broken symlinks
On CI runners, burr/examples is a relative symlink ('../examples') that
may not resolve from the process's working directory β os.path.exists
returns False for a broken link while the link itself is still present
on disk. That made _prepare_wheel_contents skip the removal branch and
then fail on os.makedirs with 'File exists: burr/examples'.
Switch to os.path.lexists, which returns True for any directory entry
including broken symlinks, so the cleanup branch always runs when the
link is present.Apache Burr (incubating) makes it easy to develop applications that make decisions (chatbots, agents, simulations, etc...) from simple python building blocks.
Apache Burr works well for any application that uses LLMs, and can integrate with any of your favorite frameworks. Burr includes a UI that can track/monitor/trace your system in real time, along with pluggable persisters (e.g. for memory) to save & load application state.
Link to documentation. Quick (<3min) video intro here. Longer video intro & walkthrough. Blog post here. Join discord for help/questions here.
Install from pypi:
pip install "burr[start]"
(see the docs if you're using poetry)
Then run the UI server:
burr
This will open up Burr‘s telemetry UI. It comes loaded with some default data so you can click around. It also has a demo chat application to help demonstrate what the UI captures enabling you too see things changing in real-time. Hit the “Demos” side bar on the left and select chatbot. To chat it requires the OPENAI_API_KEY environment variable to be set, but you can still see how it works if you don’t have an API key set.
Next, start coding / running examples:
git clone https://github.com/apache/burr && cd burr/examples/hello-world-counter python application.py
You'll see the counter example running in the terminal, along with the trace being tracked in the UI. See if you can find it.
For more details see the getting started guide.
With Apache Burr you express your application as a state machine (i.e. a graph/flowchart). You can (and should!) use it for anything in which you have to manage state, track complex decisions, add human feedback, or dictate an idempotent, self-persisting workflow.
The core API is simple -- the Burr hello-world looks like this (plug in your own LLM, or copy from the docs for gpt-X)
from burr.core import action, State, ApplicationBuilder @action(reads=[], writes=["prompt", "chat_history"]) def human_input(state: State, prompt: str) -> State: # your code -- write what you want here, for example chat_item = {"role" : "user", "content" : prompt} return state.update(prompt=prompt).append(chat_history=chat_item) @action(reads=["chat_history"], writes=["response", "chat_history"]) def ai_response(state: State) -> State: # query the LLM however you want (or don't use an LLM, up to you...) response = _query_llm(state["chat_history"]) # Burr doesn't care how you use LLMs! chat_item = {"role" : "system", "content" : response} return state.update(response=content).append(chat_history=chat_item) app = ( ApplicationBuilder() .with_actions(human_input, ai_response) .with_transitions( ("human_input", "ai_response"), ("ai_response", "human_input") ).with_state(chat_history=[]) .with_entrypoint("human_input") .build() ) *_, state = app.run(halt_after=["ai_response"], inputs={"prompt": "Who was Aaron Burr, sir?"}) print("answer:", app.state["response"])
Apache Burr includes:

Apache Burr can be used to power a variety of applications, including:
As well as a variety of (non-LLM) use-cases, including a time-series forecasting simulation, and hyperparameter tuning.
And a lot more!
Using hooks and other integrations you can (a) integrate with any of your favorite vendors (LLM observability, storage, etc...), and (b) build custom actions that delegate to your favorite libraries (like Apache Hamilton).
Apache Burr will not tell you how to build your models, how to query APIs, or how to manage your data. It will help you tie all these together in a way that scales with your needs and makes following the logic of your system easy. Burr comes out of the box with a host of integrations including tooling to build a UI in streamlit and watch your state machine execute.
See the documentation for getting started, and follow the example. Then read through some of the concepts and write your own application!
While Apache Burr is attempting something (somewhat) unique, there are a variety of tools that occupy similar spaces:
| Criteria | Apache Burr | Langgraph | temporal | Langchain | Superagent | Apache Hamilton |
|---|---|---|---|---|---|---|
| Explicitly models a state machine | β | β | β | β | β | β |
| Framework-agnostic | β | β | β | β | β | β |
| Asynchronous event-based orchestration | β | β | β | β | β | β |
| Built for core web-service logic | β | β | β | β | β | β |
| Open-source user-interface for monitoring/tracing | β | β | β | β | β | β |
| Works with non-LLM use-cases | β | β | β | β | β | β |
Apache Burr is named after Aaron Burr, founding father, third VP of the United States, and murderer/arch-nemesis of Alexander Hamilton. What‘s the connection with (Apache) Hamilton? We imagine a world in which Burr and Hamilton lived in harmony and saw through their differences to better the union. Originally Apache Burr was built as a harness to handle state between executions of Apache Hamilton DAGs (because DAGs don’t have cycles), but realized that it has a wide array of applications and decided to release it more broadly.
“After evaluating several other obfuscating LLM frameworks, their elegant yet comprehensive state management solution proved to be the powerful answer to rolling out robots driven by AI decision-making.”
Ashish Ghosh CTO, Peanut Robotics
“Of course, you can use it [LangChain], but whether it‘s really production-ready and improves the time from ‘code-to-prod’ [...], we’ve been doing LLM apps for two years, and the answer is no [...] All these ‘all-in-one’ libs suffer from this [...]. Honestly, take a look at Burr. Thank me later.”
Reddit user cyan2k LocalLlama, Subreddit
“Using Burr is a no-brainer if you want to build a modular AI application. It is so easy to build with, and I especially love their UI which makes debugging a piece of cake. And the always-ready-to-help team is the cherry on top.”
Ishita Founder, Watto.ai
“I just came across Burr and I‘m like WOW, this seems like you guys predicted this exact need when building this. No weird esoteric concepts just because it’s AI.”
Matthew Rideout Staff Software Engineer, Paxton AI
“Burr's state management part is really helpful for creating state snapshots and building debugging, replaying, and even evaluation cases around that.”
Rinat Gareev Senior Solutions Architect, Provectus
“I have been using Burr over the past few months, and compared to many agentic LLM platforms out there (e.g. LangChain, CrewAi, AutoGen, Agency Swarm, etc), Burr provides a more robust framework for designing complex behaviors.”
Hadi Nayebi Co-founder, CognitiveGraphs
"Moving from LangChain to Burr was a game-changer!
- Time-Saving: It took me just a few hours to get started with Burr, compared to the days and weeks I spent trying to navigate LangChain.
- Cleaner Implementation: With Burr, I could finally have a cleaner, more sophisticated, and stable implementation. No more wrestling with complex codebases.
- Team Adoption: I pitched Burr to my teammates, and we pivoted our entire codebase to it. It's been a smooth ride ever since."
Aditya K. DS Architect, TaskHuman
While Apache Burr is stable and well-tested, we have quite a few tools/features on our roadmap!
If you want to avoid self-hosting the above solutions we‘re building Burr Cloud. To let us know you’re interested sign up here for the waitlist to get access.
We welcome contributors! To get started on developing, see the developer-facing docs.
Users who have contributed core functionality, integrations, or examples.
Users who have contributed small docs fixes, design suggestions, and found bugs
Apache Burr is released under the Apache 2.0 License. See LICENSE for details.
We're very supportive of changes by new contributors, big or small! Make sure to discuss potential changes by creating an issue or commenting on an existing one before opening a pull request. Good first contributions include creating an example or an integration with your favorite Python library!
To contribute, checkout our contributing guidelines, our developer setup guide, and our Code of Conduct.