Model or dataset
unicity-aos/capsule-react avatar
unicity-aos/capsule-react

Capsule React is the shell that walks a turn through five capsules

ReAct loop coordinator. Stateless state machine for reasoning-and-action cycle. Part of Unicity AOS.

5,036 stars13 forksRustApache-2.0

At a glance

What is it?
This Rust capsule carries no inference logic at all. It is the control flow layer of the Astrid OS reasoning and action cycle, moving a turn from Idle through identity, prompt building, streaming and tool dispatch, and parking per turn correlation keys in the capsule KV store.
Who is it for?
Adopt it when you want the ReAct cycle as swappable infrastructure rather than logic buried in your agent, and when you accept that a turn is a sequence of events across five other capsules. Skip it if you need one crate to call a model, run tools or keep history, because none of that lives here.
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 128 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • unicity-aos/capsule-react5,036 ★ · -8
Star history
Repository2026-09-232026-11-14
unicity-aos/capsule-react5k5k

-8 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The state diagram ends in an ellipsis, so it is not a transition table

The published cycle is one line of text:

text
Idle -> AwaitingIdentity -> AwaitingPromptBuild -> Streaming -> AwaitingTools -> Streaming -> ... -> Idle

Two things in that line matter. Streaming appears twice, so token streaming is not a single phase between prompt build and tools: the turn comes back to it after tool dispatch as well. And the diagram closes with an ellipsis before returning to Idle, which means intermediate states are not enumerated. You cannot derive a complete transition table from it, and no failure, timeout or cancel state appears anywhere in the line. If you are writing a tool or a provider against this coordinator, plan on reading the source rather than the diagram, because the diagram tells you the order of the happy path and nothing about how a broken step is represented. The cycle itself is fetch context, think, act, observe, repeat.

Stateless here means no history, not no state

The description calls this a stateless state machine, and the README places ephemeral per turn state in the capsule KV store under three keys:

text
react.turn.{session_id}
react.req2sess.{request_id}
react.call2sess.{call_id}

So the stateless label describes what the loop does not own, which is conversation history, rather than claiming it stores nothing. The turn record and the two correlation maps live in KV, which is what lets a cycle survive being spread across capsules: the Session capsule fetches conversation history and persists turn results, and the loop itself only holds the state needed to route the turn it is currently driving. The README is explicit that this is control flow state and that history lives in the session capsule. The practical line to hold: if your data must outlive one turn, it belongs in Session, because the keys above are scoped to the turn.

Five capsules do the work, and this one only routes events

The react loop contains no inference logic. It is pure control flow coordinating five other capsules over the IPC event bus. Session fetches conversation history and persists turn results. Identity builds the system prompt from workspace config. Prompt Builder merges plugin contributions into the final prompt. Provider, with Anthropic given as the example, streams LLM responses. Tool Router dispatches tool calls and collects results. Everything expensive, everything stateful about the conversation, and everything that touches a model lives in those five, and the README states plainly that this capsule does not call LLMs, execute tools, build prompts, or store messages. That boundary is the reason the orchestrator is replaceable: substituting a different orchestration strategy, with debate, MCTS and chain-of-verification named as examples, is stated to change the agent's behaviour without touching any other capsule.

Request and call ids are what hold a turn together

The two correlation keys are the mechanism that keeps one turn coherent while five capsules and a streaming provider are involved. `react.req2sess.{request_id}` maps a request to its session, and `react.call2sess.{call_id}` maps a tool call back to the session that issued it, with `react.turn.{session_id}` holding the current turn state. Tool results do not come back on the same path they went out on, so without a call keyed mapping a returned result has no obvious owner, and without the request key a resumed turn has no obvious session. One naming detail to keep in mind when you write tooling around it: the keys are prefixed `react.` even though the crate is `astrid-capsule-react`, so key prefixes and crate names do not line up. If you are grepping KV for turn state, grep the prefix, not the package name.

cdylib and a wasm target make this an artifact rather than a library

Cargo.toml marks the package `publish = false`, and the lib section sets `crate-type = ["cdylib"]`. There is no crate to add to your own Cargo.toml and nothing to fetch from a registry: you take the repository and build a WebAssembly module. The two commands that do it are in the README:

bash
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --release

The target has to be added first, since the host toolchain does not ship it, and the artifact is produced for `wasm32-unknown-unknown`, which is what the OS loads as a capsule. The rest of the top level fits that picture: `Capsule.toml` is the capsule manifest, `rust-toolchain.toml` pins the compiler, `.cargo/` holds build configuration, `Cargo.lock` is committed so the build resolves the same versions, and `src/` holds the Rust. Edition 2024 in the package section sets the language floor for all of it.

The release profile trades build time for size, and aborts on panic

The release profile is tuned for a small shipped module:

toml
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = true
panic = "abort"

`opt-level = "z"` optimizes for size rather than speed, which is the right target for something loaded into an agent runtime, and `strip = true` removes symbols from the artifact. Two of these have consequences worth planning around. `codegen-units = 1` with `lto = true` serializes and re-optimizes the whole crate graph, so builds take noticeably longer than a default release build. `panic = "abort"` means there is no unwinding: a panic in the loop ends the module instance rather than propagating to a caller that could catch it. Dependencies are the small set the coordinator needs: `astrid-sdk` 0.7 with the derive feature, `serde` 1.0 with derive, `serde_json` 1.0, and `uuid` 1.22 with v4, serde and rng-getrandom, where the v4 ids come from the platform random source the feature pulls in.

Two license files, one SDK minor, and a 0.x version number

Licensing needs one clarification before you copy anything. The README states dual licensing under MIT and Apache 2.0 with copyright 2025 to 2026 Joshua J. Bouw and Unicity Labs, and both `LICENSE-MIT` and `LICENSE-APACHE` sit at the top level, while the license field in the repository metadata says Apache-2.0 alone. Pick one deliberately for derived work rather than assuming from the metadata. The coupling is on the SDK side: `astrid-sdk = { version = "0.7", features = ["derive"] }` pins a single minor version of the SDK this capsule was written against. The version story is equally candid. The crate is at 0.2.2, matching the v0.2.2 release dated 2026-07-09, after v0.2.1 and v0.2.0 both dated 2026-07-02, and the last push to the repository is 2026-07-09 with nothing archived. A 0.x number on a capsule that holds no model logic still means the interface can move.

Editorial conclusion

Adopt it when you want the ReAct cycle as swappable infrastructure rather than logic buried in your agent, and when you accept that a turn is a sequence of events across five other capsules. Skip it if you need one crate to call a model, run tools or keep history, because none of that lives here. Before you build, read Capsule.toml and rust-toolchain.toml, decide MIT or Apache 2.0, and check that your astrid-sdk minor matches the 0.7 this capsule pins.

Frequently asked questions

What does capsule-react do inside Astrid OS?

It is the ReAct loop coordinator, the shell of the OS model: it drives the reasoning and action cycle of fetch context, think, act, observe, repeat, and contains no inference logic of its own.

Which capsules does capsule-react coordinate?

Five, over the IPC event bus: Session for conversation history and turn results, Identity for the system prompt from workspace config, Prompt Builder for plugin contributions, Provider for streamed LLM responses, and Tool Router for dispatching tool calls.

What state does capsule-react keep?

Ephemeral per turn state in the capsule KV store, under react.turn.{session_id}, react.req2sess.{request_id} and react.call2sess.{call_id}. Conversation history is not kept here; it lives in the session capsule.

How do I build capsule-react?

Add the target with rustup target add wasm32-unknown-unknown, then run cargo build --target wasm32-unknown-unknown --release. The crate is a cdylib with publish set to false, so it is built from the repository rather than installed from a registry.

Which dependencies does capsule-react pull in?

astrid-sdk 0.7 with the derive feature, serde 1.0 with derive, serde_json 1.0, and uuid 1.22 with the v4, serde and rng-getrandom features.

How is capsule-react licensed?

The README states dual licensing under MIT and Apache 2.0, copyright 2025 to 2026 Joshua J. Bouw and Unicity Labs, and both LICENSE-MIT and LICENSE-APACHE are present at the top level.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. unicity-aos/capsule-react on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/unicity-aos-capsule-react.svg)](https://hysenlabs.com/projects/unicity-aos-capsule-react)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/unicity-aos-capsule-react.svg)](https://hysenlabs.com/projects/unicity-aos-capsule-react)

Was this useful?