# Swink Agent
[](https://github.com/SuperSwinkAI/Swink-Agent/actions/workflows/ci.yml)
[](https://crates.io/crates/swink-agent)
[](https://docs.rs/swink-agent)
[](https://blog.rust-lang.org/2026/04/16/Rust-1.95.0/)
[](LICENSE)
A pure-Rust library for building LLM-powered agentic loops. Provider-agnostic core with pluggable streaming, concurrent tool execution, and lifecycle events.
## Workspace
| `swink-agent` | lib | Agent loop, tool system, streaming traits, retry, error types |
| `swink-agent-adapters` | lib | `StreamFn` adapters — Anthropic, OpenAI, Google Gemini, Ollama, Azure, xAI, Mistral, Bedrock, Proxy |
| `swink-agent-policies` | lib | 11 feature-gated policy implementations (budget, sandbox, PII, audit, etc.) |
| `swink-agent-memory` | lib | Session persistence, summarization compaction |
| `swink-agent-local-llm` | lib | On-device inference — SmolLM3-3B (default), Gemma 4 (opt-in `gemma4` feature), EmbeddingGemma-300M (embeddings) |
| `swink-agent-eval` | lib + bin | Evaluation harness — efficiency scoring, budget guards, gate checks, audit trails, plus feature-gated judge-backed and deterministic evaluators, multi-turn simulation, trace ingestion (OTLP / Langfuse / OpenSearch / CloudWatch), Console/JSON/Markdown/HTML/LangSmith reporters, and the `swink-eval` CLI (`cli` feature) |
| `swink-agent-eval-judges` | lib | Per-provider `JudgeClient` implementations (Anthropic, OpenAI, Bedrock, Gemini, Mistral, Azure, xAI, Ollama, Proxy) with `Blocking<Provider>JudgeClient` sync wrappers behind feature flags |
| `swink-agent-evolve` | lib | Eval-driven self-improvement loop for prompts and tool schemas (Spec 044) |
| `swink-agent-artifacts` | lib | Versioned artifact storage (filesystem + in-memory backends) |
| `swink-agent-auth` | lib | OAuth2 credential management and refresh |
| `swink-agent-mcp` | lib | Model Context Protocol integration (stdio/SSE) |
| `swink-agent-patterns` | lib | Multi-agent orchestration patterns (pipeline, parallel, loop) |
| `swink-agent-plugin-web` | lib | Web browsing and search plugin |
| `swink-agent-rpc` | lib + bin | JSON-RPC 2.0 agent service and `swink-agentd` daemon over Unix sockets (Spec 045) |
| `swink-agent-macros` | proc-macro | `#[derive(ToolSchema)]` and `#[tool]` proc macros |
| `swink-agent-tui` | lib + bin | Interactive terminal UI with markdown, syntax highlighting, tool panel |
| `xtask` | bin | Developer workflow tasks such as catalog and release validation |
## Feature Matrix
| `swink-agent` | `builtin-tools`, `transfer` | `artifact-store`, `artifact-tools`, `hot-reload`, `plugins`, `testkit`, `tiktoken`, `otel` | Core loop and tool/runtime surface stay provider-agnostic. |
| `swink-agent-adapters` | none (opt in per provider) | Per-provider adapter features | Remote HTTP/SSE adapters are isolated from the core crate. |
| `swink-agent-policies` | `all` | Individual policy features such as `budget`, `sandbox`, `audit`, `pii` | Reusable loop/app policies stay independently gateable. |
| `swink-agent-local-llm` | SmolLM3 local runtime | Backend/model features such as `cuda`, `metal`, `vulkan`, `gemma4` | Requires LLVM/libclang because `llama-cpp-sys-2` runs `bindgen`. |
| `swink-agent-eval` | Spec 023 deterministic evals | `judge-core`, `all-evaluators`, `simulation`, `generation`, `trace-ingest`, `trace-otlp`, `trace-langfuse`, `trace-opensearch`, `trace-cloudwatch`, `telemetry`, `html-report`, `langsmith`, `cli`, `multimodal`, `yaml` | Advanced evals remain mostly opt-in so no-default builds stay slim. |
| `swink-agent-eval-judges` | Minimal shared client surface | Per-provider judge features plus `all-judges` | Provider credentials and transport details live in the separate judge-client crate. |
| `swink-agent-tui` | Terminal UI with remote providers | `local`, `full` | `local` brings in on-device inference; `full` enables the broader optional surface. |
## Key Ideas
- **`StreamFn`** is the only provider boundary — implement it to add a new LLM backend.
- **`AgentTool`** trait + JSON Schema validation for tool definitions.
- Tools execute concurrently within a turn; steering callbacks can interrupt mid-batch.
- Errors stay in the message log — the loop keeps running. Typed `AgentError` variants for callers.
- Events are push-only (`AgentEvent` stream). No inward mutation through events.
- No `unsafe` code. No global mutable state.
- Optional `tiktoken` support ships a built-in `TiktokenCounter` for more accurate context budgets.
## Quick Reference
```bash
cargo run -p swink-agent-tui # launch the TUI (remote/Ollama defaults)
cargo run -p swink-agent-tui --features local # include bundled local-LLM support
cargo run -p swink-agent-eval --features cli --bin swink-eval -- --help
cargo test --workspace # default-feature workspace test baseline
just validate # full local gate: fmt, clippy, tests, feature gates, package preflight
```
Workspace-wide builds need LLVM/libclang (for `swink-agent-local-llm`) — see [docs/getting_started.md](docs/getting_started.md#build).
For the advanced evaluation surface, see [`eval/README.md`](eval/README.md) for evaluator/reporter usage and [`eval-judges/README.md`](eval-judges/README.md) for provider feature flags and credential setup.
## Hot-Reloaded Script Tools
When the `hot-reload` feature is enabled, `ScriptTool` definitions use a
top-level `[parameters_schema]` TOML section, and `command` interpolates
runtime arguments with `{param}` placeholders:
```toml
name = "greet"
description = "Greet a person by name"
command = "echo 'Hello, {name}!'"
[parameters_schema]
type = "object"
required = ["name"]
[parameters_schema.properties.name]
type = "string"
description = "The name to greet"
```
## Example: Build a Custom Agent
Wire up an LLM provider, register tools, and launch the interactive TUI — all in one file:
```rust
use swink_agent::{AgentOptions, BashTool, ModelConnections, ReadFileTool, WriteFileTool};
use swink_agent_adapters::build_remote_connection_for_model;
use swink_agent_local_llm::default_local_connection;
use swink_agent_tui::{TuiConfig, launch, restore_terminal, setup_terminal};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenvy::dotenv().ok();
let connections = ModelConnections::new(
build_remote_connection_for_model("claude-sonnet-4-6")?,
vec![
build_remote_connection_for_model("gpt-4.1")?,
default_local_connection()?,
],
);
let tools = vec![
BashTool::new().into_tool(),
ReadFileTool::new().into_tool(),
WriteFileTool::new().into_tool(),
];
let options =
AgentOptions::from_connections("You are a helpful assistant.", connections)
.with_tools(tools);
let mut terminal = setup_terminal()?;
let result = launch(TuiConfig::default(), &mut terminal, options).await;
restore_terminal()?;
result
}
```
## More Examples
Runnable examples are in [SuperSwinkAI/Swink-Agent-Examples](https://github.com/SuperSwinkAI/Swink-Agent-Examples):
| `simple_prompt` | Create an Agent with a mock stream function, send a prompt, print the result |
| `with_tools` | Register BashTool / ReadFileTool / WriteFileTool and wire up the approval callback |
| `custom_adapter` | Implement the `StreamFn` trait for a custom provider |
| `custom_agent` | Full agent with Anthropic adapter, tools, and interactive TUI |
See [docs/getting_started.md](docs/getting_started.md) for setup and configuration.
See [docs/architecture/HLD.md](docs/architecture/HLD.md) for system design.
See [docs/planning/PRD.md](docs/planning/PRD.md) for product requirements.