Framework
ldclabs/anda avatar
ldclabs/anda

Anda splits an agent runtime into five crates, and versions each one on its own

🤖 An AI agent framework built with Rust.

442 stars55 forksRustApache-2.0

At a glance

What is it?
A Rust framework for composable AI agent runtimes, with model routing by tier label, per-agent execution contexts, and tool bundles you survey before expanding. The workspace declares a dual MIT or Apache-2.0 licence that the README describes as MIT only.
Who is it for?
Adopt Anda if you are building an agent runtime in Rust and want the seams defined for you, since the traits, contexts and routing labels are the parts that are tedious to get right and expensive to change later. Do not adopt it for a single-agent script, where five crates and an Internet Computer dependency list is more structure than the problem needs.
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 4 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 October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Five crates, and a deliberate decision not to share a version number

The workspace is five member crates, and the tree in the README names the job of each:

sh
anda/
├── anda_cli/              # Command-line interface for Anda engine servers
├── anda_core/             # Core traits, types, and runtime contracts
├── anda_engine/           # Agent runtime, orchestration, contexts, models, and extensions
├── anda_engine_server/    # HTTP server for serving one or more Anda engines
└── anda_web3_client/      # Web3 client for non-TEE environments

The split separates the contracts from the runtime and from the way the runtime is served, which is the arrangement that lets an application builder depend on the server without pulling the extension machinery.

The versioning decision is explained in a comment in `Cargo.toml` rather than left implicit. Each member crate is versioned independently and sets its own `version`, so no shared default is declared in the workspace package, on the stated grounds that a shared value would go stale and match no published crate.

That has a visible consequence. The repository tags run v0.8.0, then v0.12.0, then v0.15.0, while the workspace depends on sibling crates at 0.14. The tag on this repository is not the version of anything it depends on, and it is not a number you should copy into a dependency line.

Model routing is a label, and the provider sits behind one contract

The engine routes completion requests through labelled model tiers rather than through a hardcoded provider call. The labels named in the README are `primary`, `pro`, `flash` and `lite`.

The mechanism is that provider-specific adapters stay behind a common request and output contract. The application says which tier it wants and what the request is; which vendor or endpoint serves that tier is the adapter's problem.

That is a smaller claim than it first looks, and worth stating plainly: the labels are names the application chooses, not capabilities the engine discovers. There is no description here of what happens when a tier has no provider configured, or whether a request falls back to another tier, so that behaviour is not written down in the README.

What the arrangement does buy is that swapping a provider is an adapter change rather than a change at every call site. In a runtime where the same agent calls models from several places, that is the property that matters most in practice.

CompletionRunner owns the turn loop, and subagents get a shared budget

Runtime orchestration is the job of `CompletionRunner`, and the README enumerates what it handles: iterative model turns, tool calls, agent calls, usage accounting, artifacts, steering messages, follow-up messages, cancellation, and compact continuation handoffs for long-running sessions.

That list is the specification. It tells you a turn is not just a request and a response, since accounting, artifacts, steering input and cancellation all have to be threaded through it.

Subagents are described separately, with detail that suggests they were the harder part. They add root-scoped identity, turn-completion events, bounded messaging and shared budgets, plus opt-in idle checkpoints and explicit context handoffs. Bounded messaging and a shared budget are the two that keep a subagent from becoming an unbounded cost, and the fact that idle checkpoints are opt-in rather than default is a deliberate choice about who pays for idle work.

The subagent lifecycle has its own document at `docs/subagents.md`, separate from the architecture overview, which puts the subagent path in the position of the part of the system that changes most often.

BaseCtx and AgentCtx give each agent its own cache, storage and cancel switch

Scoped execution is handled by two context types. `BaseCtx` and `AgentCtx` provide isolated state, cache, object storage, HTTP calls, signed calls, cancellation, and child contexts, for each agent or tool.

Isolation is the point. Two agents running in the same process do not share a cache or an object store namespace unless something deliberately hands one to the other, and child contexts make that nesting explicit rather than ambient.

Two entries carry more weight than the rest. Signed calls mean an agent can make a request that carries a signature without the framework owning the credential, which is how a runtime serves a hosted agent that must prove who it is. Cancellation is per context, so a long-running tool call can be abandoned without tearing down the turn that started it.

The relationship to the subagent work above is direct: root-scoped identity and shared budgets are properties of the context tree, so the isolation is not housekeeping. It is the mechanism the budget and the identity are enforced through.

tools_groups then tools_select, so a bundle is surveyed before it is expanded

Tool discovery is deliberately two-step. Static tools, dynamic providers and MCP servers can expose capability groups, and an agent surveys the related bundles with `tools_groups` before expanding one with `tools_select`, and only then does it get the schemas.

This is a context-budget decision rather than an API convenience. A runtime with many tool providers would otherwise push every schema into every prompt, and the two-step split means an agent pays for the schema of a tool it actually intends to call.

MCP integrations get a longer list: bounded catalogs and transport input, stable routes, model-facing image results, configurable call policies, and opt-in elicitation and resource APIs. Stable routes and configurable call policies are the two that matter when an agent runs unattended, since they are what stops a renamed tool or a changed policy from silently altering behaviour.

The MCP details live in `MCP_INTEGRATION.md` at the repository root rather than in the docs directory, which is a small signal about where that work is happening.

Filesystem access and shell access are separate grants

The extension list separates two things that agent frameworks usually bundle together. Restricted file agents can register filesystem tools without being granted shell access.

Coding agents take a different route: they opt into a shell, session and patch bundle, which comes with bounded output, supervised processes, and optional macOS and Linux process sandboxing.

That is the design decision worth taking away. The filesystem-only agent cannot run a command, and the coding agent that can run commands gets supervision and optional OS-level sandboxing rather than a bare shell. Bounded output matters for the same reason the context budget matters in `tools_select`: an agent that reads an unbounded log is an agent whose next turn does not fit.

Skills follow the same discipline. File-backed skills carry bounded catalogs, stable identities, paginated package resource reads, explicit-use policies and host-owned dependency preflight, and notes support bounded lookup with optional context indexes. Validated session tasks are described as surviving context compression, which is the one claim here about long sessions that touches the model's context window directly.

Cargo.toml says MIT OR Apache-2.0 and the README says MIT

The licence is declared three ways and they do not agree.

`Cargo.toml` sets `license = "MIT OR Apache-2.0"`, a dual licence. The README states that the repository is licensed under the MIT License and points at `LICENSE-MIT` for the full text. Both `LICENSE-APACHE` and `LICENSE-MIT` sit in the root, so the files needed for either reading are present, and the repository's licence field reports Apache-2.0.

In practice the dual declaration is the one that binds a consumer: it is what a published crate carries into the registry, and it is what the MIT file being named first in the README does not override. Anyone who needs to confirm which terms apply should read both files rather than either summary.

The copyright line is LDC Labs, dated 2026. Products built on the framework are listed as Anda Brain, described as a persistent memory and cognition product, and Anda Bot, a personal assistant and application runtime. The related protocol is KIP, the Knowledge Interaction Protocol, used by the memory tools.

The dependency list is an Internet Computer stack, and the README introduction never says so

The workspace dependencies explain more about the project's centre of gravity than the README introduction does. Alongside axum, tokio with its full feature set, serde, reqwest and object_store, the list includes candid, ic-agent, ic_cose, ic_ed25519, ic-secp256k1, ic_auth_types, ic_auth_verifier, ic_tee_cdk and ic_tee_gateway_sdk, plus anda_cloud_cdk, anda_kip, anda_db and anda_cognitive_nexus.

The crate description is explicit about it: Anda is an AI agent framework built with Rust, powered by ICP and TEEs. The declared keywords are ai-agent, icp and tee. One workspace member, anda_web3_client, is described as a client for non-TEE environments, which implies the TEE path is the default.

The README introduction, by contrast, describes composability, type-safe extension points, asynchronous execution and runtime control, and does not mention ICP, TEEs or Web3 once. Someone deciding whether to evaluate this framework for a non-Web3 application should read `Cargo.toml` before the README, because the README will not warn them off.

The build itself is plain Cargo. The Makefile wraps it in three targets: `lint` runs `cargo fmt` then clippy across all targets and features, `fix` runs fmt and clippy's fixer across the workspace and tests, and `test` runs the full workspace test suite with all features and no output capture.

Editorial conclusion

Adopt Anda if you are building an agent runtime in Rust and want the seams defined for you, since the traits, contexts and routing labels are the parts that are tedious to get right and expensive to change later. Do not adopt it for a single-agent script, where five crates and an Internet Computer dependency list is more structure than the problem needs. Two things to settle before you start: which licence you are relying on, because Cargo.toml says MIT OR Apache-2.0 while the README says MIT and points at LICENSE-MIT, and whether you need the Web3 side at all, since the crate description mentions ICP and TEEs and the README introduction mentions neither.

Frequently asked questions

What crates make up the Anda workspace?

Five of them: anda_cli as the command line for engine servers, anda_core for traits and runtime contracts, anda_engine for the agent runtime itself, anda_engine_server as an HTTP server for one or more engines, and anda_web3_client for non-TEE environments.

How does Anda choose which model handles a request?

Completion requests are routed through labelled model tiers such as primary, pro, flash or lite, while provider-specific adapters stay behind a common request and output contract. The README does not describe fallback behaviour when a tier has no provider.

Can an Anda agent use the filesystem without getting a shell?

Yes. Restricted file agents can register filesystem tools without being granted shell access, while coding agents opt into a shell, session and patch bundle with bounded output, supervised processes, and optional macOS and Linux process sandboxing.

Official sources

  1. ldclabs/anda on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
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/ldclabs-anda.svg)](https://hysenlabs.com/projects/ldclabs-anda)