Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 71 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,41 @@
# Ed

**Embed Ed.** Your app gets a brain. Your users keep their data.

Ed is an agent you drop into an application. It loads an open-weights model,
keeps the conversation, calls only the host tools you register, and hands back
replies. The model runs on the user's device — there is no metered inference
API and private context does not need to leave the device.

## Why it exists

Seven applications needed the same thing: load a model, know whether it's ready,
keep a conversation, hand back a reply. Seven times somebody wrote it again. Two
of them ended up byte-identical in three files.

None of that code was interesting. It was the wiring between an inference engine
that reports status by polling and a user interface that needs to be told —
plus the flattening of `Result<InferenceResult, _>` into one payload a view can
render either way. Ed is that layer, written once.

It deliberately doesn't own sessions, persistence, model catalogues, or
downloads. Those differ per application and stay yours.

## Onde runs the model. Ed makes it a feature.

[Onde](https://ondeinference.com) is the inference engine: weights, quantisation,
Metal and CPU backends, tokens out. Ed is the part above it your users touch.

## See it live
<p align="center">
<img src="https://raw.githubusercontent.com/ondeinference/onde/refs/heads/main/assets/onde-inference-logo.svg" alt="Onde Inference" width="96">
</p>

<h1 align="center">Ed</h1>

<p align="center">
Embed Ed. Your app gets a brain. Your users keep their data.
</p>

<p align="center">
<a href="https://crates.io/crates/ed-agent"><img src="https://img.shields.io/crates/v/ed-agent?style=flat-square&labelColor=17211D&color=235843&label=ed-agent" alt="ed-agent on crates.io"></a>
<a href="https://crates.io/crates/ed-acp"><img src="https://img.shields.io/crates/v/ed-acp?style=flat-square&labelColor=17211D&color=235843&label=ed-acp" alt="ed-acp on crates.io"></a>
<a href="https://github.com/ondeinference/ed-swift"><img src="https://img.shields.io/github/v/release/ondeinference/ed-swift?style=flat-square&labelColor=17211D&color=235843&label=Swift" alt="Swift"></a>
<a href="https://github.com/ondeinference/ed/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/ondeinference/ed/ci.yml?style=flat-square&labelColor=17211D&color=235843&label=CI" alt="CI"></a>
<a href="#license"><img src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-235843?style=flat-square&labelColor=17211D" alt="License"></a>
</p>

Ed is the agent layer above [Onde](https://ondeinference.com). It loads an
open-weights model, keeps the conversation, calls only the host tools you
register and hands back replies. The model runs on the user's device, so there
is no metered inference API and private context stays put. The `ed-acp` crates
build ACP agents (Onde Code, SplitFire Agent, siGit) on the same base.

Ed doesn't own sessions, persistence, model catalogues or downloads. Those
differ per application and stay yours.

## Install

```sh
cargo add ed-agent # embedded chat
cargo add ed-acp # ACP agent
```

- **[smbCloud MailX](https://smbcloudmail.com/en-us)** — siMail drafts replies,
summarises long threads, and helps triage the inbox. The mail never leaves the
machine to get read.
- **[Siti AI](https://github.com/getsigit/siti)** — a private assistant for
macOS, iOS, and Android, and the open reference app: its source is public, so
it's the codebase to read for a full integration.
- **[Pepak Basa Jawa Komplit](https://apps.apple.com/se/app/pepak-basa-jawa-komplit/id6752241812)**
— Joko, a Javanese tutor who answers offline, which matters where the app is
used.
- **[Rumi Learn Persian](https://apps.apple.com/se/app/rumi-l%C3%A4r-dig-persiska/id6753832408)**
— Rumi, a Persian tutor, same model, same device.
For Swift, add the package from [`ondeinference/ed-swift`](https://github.com/ondeinference/ed-swift).

## Quick start

```toml
[dependencies]
ed-agent = "1.2"
```

```rust
use ed_agent::{Ed, GgufModelConfig};

Expand All @@ -57,39 +46,50 @@ let reply = ed.send("Summarise this thread.").await;
println!("{}", reply.reply.unwrap_or_default());
```

Stream a reply with `Ed::stream` (plain chat) or let `Ed::run` forward deltas to
`EventSink::text_delta`. `Ed::restore_history` loads a saved conversation,
`Ed::generate` is a one-shot call that leaves the history alone, and
`Ed::set_system_prompt` / `set_sampling` change the model's settings. These
three need a loaded model. Persistence stays yours; implement `SessionStore`
over whatever you already have.
Streaming, history, tools and approvals are covered in [`crates/ed-agent`](crates/ed-agent).

Construct with `Ed::with_agent` to provide the executor for registered tools
and the approval handler for mutating tools. Read-only tools run directly;
mutating tools must receive `AllowOnce` or `AllowForSession` first.
## Use it your way

## Crates
- **In your app:** [`ed-agent`](crates/ed-agent), plus [`ed-agent-tauri`](crates/ed-agent-tauri) for Tauri and [`ed-agent-ffi`](crates/ed-agent-ffi) for Swift.
- **As an ACP agent:** [`ed-acp`](crates/ed-acp) with a `Profile`, and [`ed-acp-tui`](crates/ed-acp-tui) for a terminal UI.
- **Inside a Tauri app:** [`ed-acp-tauri`](crates/ed-acp-tauri) runs an ACP agent in process or an external stdio agent.
- **With Claude:** [`ed-claude`](crates/ed-claude), a profile on the Anthropic API with the user's key.
- **With MCP servers:** [`ed-mcp`](crates/ed-mcp). Onde accounts: [`ed-onde-account`](crates/ed-onde-account). Tests: [`ed-acp-testkit`](crates/ed-acp-testkit).

| Crate | What it's for |
| --- | --- |
| [`ed-agent`](crates/ed-agent) | The agent. No framework dependency. |
| [`ed-agent-ffi`](crates/ed-agent-ffi) | UniFFI bridge used by the Swift XCFramework. |
| [`ed-agent-tauri`](crates/ed-agent-tauri) | Tauri bindings: a sink that emits to the webview, the commands it invokes, and `EdSessions` for apps with a chat history and webview-answered approvals. |
## In production

The Onde Agent Platform crates, for agents that editors drive over the Agent Client Protocol
(ACP). SplitFire Agent is built on them.
[smbCloud MailX](https://smbcloudmail.com/en-us), [Siti AI](https://github.com/getsigit/siti) (the open reference app),
[Pepak Basa Jawa Komplit](https://apps.apple.com/se/app/pepak-basa-jawa-komplit/id6752241812) and
[Rumi](https://apps.apple.com/se/app/rumi-l%C3%A4r-dig-persiska/id6753832408).

| Crate | What it's for |
| --- | --- |
| [`ed-acp`](crates/ed-acp) | An ACP v1 server: sessions, auth, the turn loop on Onde Cloud, tool approval, workspace tools and MCP. A product supplies a `Profile`. |
| [`ed-acp-tui`](crates/ed-acp-tui) | A terminal UI for any ACP agent. |
| [`ed-mcp`](crates/ed-mcp) | MCP client glue over `rmcp`, the official Rust SDK: stdio and streamable HTTP servers, bearer tokens, tool namespacing, timeouts, progress and cancellation. With the `agent` feature, `McpExecutor` serves a toolset to Ed as tools. |
| [`ed-onde-account`](crates/ed-onde-account) | Onde Inference account client: sign in, activate an app and get its Onde Cloud API key through ondeinference.com, with no Onde secrets in the host app. |
| [`ed-acp-testkit`](crates/ed-acp-testkit) | Mock Onde Cloud endpoint, raw ACP client, the ACP registry probe and the ACP v1 conformance suite. |
## Docs

Free the intelligence.
Each crate has its own README:
[`ed-agent`](crates/ed-agent/README.md),
[`ed-agent-tauri`](crates/ed-agent-tauri/README.md),
[`ed-agent-ffi`](crates/ed-agent-ffi),
[`ed-acp`](crates/ed-acp/README.md),
[`ed-acp-tui`](crates/ed-acp-tui/README.md),
[`ed-acp-tauri`](crates/ed-acp-tauri),
[`ed-claude`](crates/ed-claude),
[`ed-mcp`](crates/ed-mcp/README.md),
[`ed-onde-account`](crates/ed-onde-account/README.md),
[`ed-acp-testkit`](crates/ed-acp-testkit/README.md).

## Contributing

Open pull requests against `development`. Before you push:

```sh
cargo fmt --all -- --check && cargo clippy --locked --workspace --all-targets -- -D warnings && cargo test --locked --workspace
```

## License

MIT or Apache-2.0, at your option. See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE).

## Copyright

Free the intelligence.

© 2026 [Onde Inference](https://ondeinference.com).
Licensed under MIT or Apache-2.0.
Loading