entelix 0.6.1

entelix — web-service-native Rust agentic AI SDK (facade re-export crate)
Documentation
# entelix

[![Rust 1.95](https://img.shields.io/badge/rust-1.95.0%2B-orange?style=flat-square&logo=rust)](https://www.rust-lang.org)
[![Edition 2024](https://img.shields.io/badge/edition-2024-blueviolet?style=flat-square)]()
[![License: MIT](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)

> **English** | **[한국어]README.ko.md**

> **Where every agent realizes its purpose.**

**General-purpose agentic-AI SDK in Rust.** Build any agent that runs an LLM-driven control loop with tools, memory, and durable state. Multi-tenant from day 1. OpenTelemetry GenAI semconv-native. Architectural invariants enforced by CI. Anthropic *managed-agents* shape. LangChain + LangGraph parity.

---

## Why entelix?

- **Multi-tenant first**`TenantId` mandatory at every persistence boundary; Postgres `FORCE ROW LEVEL SECURITY` is defense-in-depth on every backend; cross-tenant leakage is structurally impossible by API design.
- **Type-enforced architecture** — sealed `RenderedForLlm<T>` carrier (compile-time LLM / operator channel separation); sealed `CompactedHistory` (`tool_call` / `tool_result` pair invariant impossible to break); `TenantId` newtype with validating constructor.
- **Production observability from day 1** — OpenTelemetry GenAI semconv `gen_ai.*` attributes; cost emits transactionally (`Ok` branch only); typed `AuditSink` channel for sub-agent dispatch, supervisor handoff, wake-resume, memory recall, usage-limit breach, context-compaction, tool-error termination, and HITL pause-resume.
- **Cross-vendor IR** — Anthropic Messages, OpenAI Chat, OpenAI Responses, Gemini, Bedrock Converse codecs route across Direct, Bedrock (SigV4), Vertex (gcp_auth), Foundry (api-key + AAD). `LossyEncode` warnings on every coerced field, `Other { raw }` for unknown vendor signals — no silent fallback.
- **MCP first-class** — every server-initiated channel (`Roots`, `Elicitation`, `Sampling`); per-tenant `(tenant_id, server_name)` pool isolation; HTTP-only by design.
- **CI-enforced invariants**`cargo xtask invariants` runs typed-AST visitors per push: filesystem-free, naming taxonomy, silent-fallback, lock-ordering, public-API drift, supply-chain, feature-matrix.

---

## Quick Start

```bash
cargo add entelix
```

```rust
use std::sync::Arc;
use entelix::auth::ApiKeyProvider;
use entelix::codecs::AnthropicMessagesCodec;
use entelix::ir::Message;
use entelix::transports::DirectTransport;
use entelix::{ChatModel, ExecutionContext};

#[tokio::main]
async fn main() -> entelix::Result<()> {
    entelix::install_default_tls();
    let creds = Arc::new(ApiKeyProvider::anthropic(std::env::var("ANTHROPIC_API_KEY")?));
    let transport = DirectTransport::anthropic(creds)?;
    let model = ChatModel::new(AnthropicMessagesCodec, transport, "claude-opus-4-7")
        .with_system("Answer in one sentence.");

    let reply = model
        .complete(vec![Message::user("Define entelechy.")], &ExecutionContext::new())
        .await?;
    println!("{reply:?}");
    Ok(())
}
```

---

## Highlights

### Cross-vendor IR + typed structured output

```rust
let model = ChatModel::new(AnthropicMessagesCodec, transport, "claude-opus-4-7")
    .with_validation_retries(2);                     // schema-mismatch retry budget

let reply: Translation = model
    .complete_typed::<Translation>(messages, &ctx)   // typed structured output
    .await?;
```

### LCEL composition

```rust
use entelix::{ChatPromptTemplate, JsonOutputParser, RunnableExt};

let chain = prompt.pipe(model).pipe(parser);       // compile-time I/O checking
let result = chain.invoke(input, &ctx).await?;
```

### StateGraph control flow (LangGraph parity)

```rust
use entelix::{Annotated, Append, Max, StateGraph, StateMerge, RunnableLambda};

#[derive(Clone, Default, StateMerge)]
struct AgentState {
    log: Annotated<Vec<String>, Append<String>>,    // accumulated across nodes
    score: Annotated<i32, Max<i32>>,                // best-of across branches
    last_phase: String,                             // last-write-wins
}

let graph = StateGraph::<AgentState>::new()
    .add_contributing_node("plan", plan)            // typed delta + per-field merge
    .add_send_edges("plan", ["a", "b", "c"], scatter, "score")  // parallel fan-out
    .add_conditional_edges("score", router, [("plan", "plan"), ("done", entelix::END)])
    .set_entry_point("plan")
    .with_checkpointer(Arc::new(postgres_checkpointer))         // resume after crash
    .compile()?;
```

### Auto-compaction

```rust
use entelix::{HeadDropCompactor, MessageRunnableCompactionExt, SummaryCompactor};

// Drop oldest turns when context approaches threshold.
let model = my_model.with_compaction(Arc::new(HeadDropCompactor), 8_192);

// Or LLM-summary compaction.
let summariser = SummaryCompactor::new(Arc::new(summary_model));
let model = my_model.with_compaction(Arc::new(summariser), 8_192);
```

### Production HTTP server

```rust
use entelix::{AgentRouterBuilder, SERVER_DEFAULT_TENANT_HEADER};

let router = AgentRouterBuilder::new(agent)
    .with_checkpointer(Arc::clone(&postgres_checkpointer))
    .with_tenant_header(SERVER_DEFAULT_TENANT_HEADER)   // multi-tenant strict mode
    .build()?;

let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
axum::serve(listener, router).await?;
```

Endpoints: `POST /v1/threads/{thread_id}/runs`, `GET /v1/threads/{thread_id}/stream`, `POST /v1/threads/{thread_id}/wake`, `GET /v1/health`.

### Tools — built-in + `#[tool]` macro

```rust
use entelix::tool;

#[tool]
/// Add two numbers.                              // first paragraph → LLM-facing description
async fn add(_ctx: &AgentContext<()>, a: i64, b: i64) -> Result<i64> {
    Ok(a + b)
}
// Generates `Add` unit struct + `SchemaTool` impl + JSON Schema.
```

Built-ins: `HttpFetchTool` (layered SSRF defense — allowlist, DNS resolver, redirect / size caps), `CalculatorTool`, `SchemaTool` typed-I/O adapter. Sandboxed shell / file / code tools live in the `entelix-tools-coding` companion crate and delegate every syscall through the `Sandbox` trait.

### Memory patterns

`BufferMemory` (sliding window), `SummaryMemory` (rolling LLM summary), `ConsolidatingBufferMemory` (auto-summary on size threshold), `EntityMemory`, `EpisodicMemory<V>`, `SemanticMemory<E, V>` (vector retrieval), `GraphMemory<N, E>` (typed nodes + timestamped edges, BFS + shortest-path).

### MCP — every server-initiated channel

```rust
use entelix::{ChatModelSamplingProvider, McpServerConfig, StaticRootsProvider};

let server = McpServerConfig::http("https://server.example/mcp")
    .with_roots_provider(Arc::new(StaticRootsProvider::new(roots)))
    .with_sampling_provider(Arc::new(ChatModelSamplingProvider::new(chat)));
```

---

## What entelix is NOT

- **No direct filesystem / shell calls in first-party crates** — sandboxed wrappers live in `entelix-tools-coding`; every syscall delegates through the `Sandbox` trait. Concrete `Sandbox` impls (Landlock / Seatbelt / e2b / modal) ship as companion crates.
- **No local inference** — application-layer SDK; pair with `candle` / `mistral.rs` if needed.
- **No vector DB reimplementation** — production `VectorStore` impls ship as `entelix-memory-qdrant` / `entelix-memory-pgvector`; bring your own via the trait.
- **No document loaders** — that's `swiftide`'s job.
- **No Python interop** — Rust-first.

---

## Workspace

`entelix-core` is the DAG root and depends on no other entelix crate. The facade `entelix` crate gates optional sub-crates behind feature flags.

- **Canonical crate list + feature flags**[`crates/entelix/Cargo.toml`]crates/entelix/Cargo.toml (`full` enables every feature)
- **Per-crate guidance** → each `crates/<name>/CLAUDE.md`
- **Frozen public API per crate**[`docs/public-api/`]docs/public-api/ (facade excluded by design)

---

## Examples

Working examples under [`crates/entelix/examples/`](crates/entelix/examples/) — quickstart through end-to-end production workflow.

---

## Inspirations

- **Anthropic [Managed Agents]https://www.anthropic.com/engineering/managed-agents** — Session / Harness / Hand decoupling, cattle-not-pets, lazy provisioning
- **LangChain LCEL**`Runnable` + `.pipe()` composition primitive
- **LangGraph** — typed state-graph control flow + `Annotated[T, reducer]` + Checkpointer + HITL
- **OpenTelemetry [GenAI semconv]https://github.com/open-telemetry/semantic-conventions/tree/main/docs/gen-ai** — vendor-neutral observability vocabulary

---

## Reading order

1. [`CLAUDE.md`]CLAUDE.md — invariants, lock ordering, error conventions, managed-agent shape
2. [`docs/architecture/principles.md`]docs/architecture/principles.md — living design contract
3. Per-crate `crates/<name>/CLAUDE.md` — surface, crate-local rules, forbidden patterns
4. [`docs/public-api/`]docs/public-api/ — frozen per-crate API baselines

---

## Support

- [GitHub Issues]https://github.com/junyeong-ai/entelix/issues
- [Architecture Principles]docs/architecture/principles.md
- [Provider Capabilities Matrix]docs/architecture/provider-capabilities.md

---

## License

MIT.

---

<div align="center">

**English** | **[한국어]README.ko.md**

Made with Rust 🦀

</div>