https://github.com/andersonby/vv-agent-rs
Rust agent runtime, SDK, CLI, tools, and workspace backends
https://github.com/andersonby/vv-agent-rs
Last synced: 5 days ago
JSON representation
Rust agent runtime, SDK, CLI, tools, and workspace backends
- Host: GitHub
- URL: https://github.com/andersonby/vv-agent-rs
- Owner: AndersonBY
- Created: 2026-05-30T15:10:57.000Z (16 days ago)
- Default Branch: main
- Last Pushed: 2026-05-30T15:32:38.000Z (16 days ago)
- Last Synced: 2026-05-30T17:12:38.644Z (16 days ago)
- Language: Rust
- Size: 1.27 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# vv-agent-rs
[中文文档](README_ZH.md)
`vv-agent-rs` is the Rust workspace for the `vv-agent` crate: an embeddable
agent runtime, SDK, CLI, tool system, memory layer, and workspace abstraction
for model-driven automation.
It is designed around explicit agent control flow. A task is not considered
done because the model wrote a final-looking sentence; the model must call
`task_finish` to complete or `ask_user` to pause for user input. This keeps
CLI runs, SDK sessions, background runs, and distributed execution on the same
result contract.
## Architecture
```text
AgentRuntime
├── LLM client # vv-llm backed chat client, endpoint resolution, streaming
├── CycleRunner # one model turn: prompt, response, tool-call plan
├── ToolOrchestrator # tool policy, approval, dispatch, timeout, telemetry
├── RuntimeHookManager # before/after hooks for LLM, tools, and memory
├── MemoryManager # context budgeting, compaction, artifacts, session memory
├── RunHandle / RunEvent # live control, typed events, event-store replay
├── RuntimeExecutionBackend # run scheduling
│ ├── InlineBackend # synchronous default
│ ├── ThreadBackend # non-blocking task submission
│ └── DistributedBackend # checkpointed cycles with pluggable dispatch
└── WorkspaceBackend # file/object I/O boundary for tools
├── LocalWorkspaceBackend
├── MemoryWorkspaceBackend
└── S3WorkspaceBackend
```
Provider request building, endpoint transport, retries, streaming deltas, token
limits, usage accounting, and provider-specific protocol details are delegated
to the published `vv-llm` crate. `vv-agent` focuses on agent execution: prompts,
tools, hooks, memory, sessions, workspace access, and orchestration.
## Setup
Run commands from this repository root:
```bash
cd vv-agent-rs
cargo test -p vv-agent
```
Most real-model examples and the CLI read a local `vv-llm` settings file. Keep
the credential-bearing file untracked:
```bash
cp crates/vv-agent/tests/dev_settings.example.json local_settings.json
# Fill endpoint keys in local_settings.json.
```
The default settings path is `local_settings.json`. You can override it with
`VV_AGENT_LOCAL_SETTINGS` for examples or `--settings-file` for the CLI.
## Quick Start
### CLI
```bash
cargo run -p vv-agent -- \
--prompt "Summarize this repository" \
--backend deepseek \
--model deepseek-v4-pro \
--settings-file local_settings.json \
--workspace ./workspace \
--verbose
```
CLI flags:
| Flag | Purpose |
| --- | --- |
| `--prompt` | Required user task. |
| `--backend` | Backend key under `LLM_SETTINGS.backends`. |
| `--model` | Model key under the selected backend. |
| `--settings-file` | Local `vv-llm` settings file. |
| `--workspace` | Directory exposed to workspace tools. |
| `--max-cycles` | Maximum runtime cycles before stopping. |
| `--language` | Prompt/tool guidance locale. |
| `--agent-type` | Optional agent profile type such as `computer`. |
| `--verbose` | Emit per-cycle runtime events. |
### Agent + Runner SDK
Use `Agent` + `Runner` for new embedded applications. `Agent`
describes instructions, model, tools, handoffs, hooks, and defaults. `Runner`
owns model providers, workspace defaults, and execution. `RunConfig` overrides
one run without changing the agent definition, including the public
`ExecutionMode` for inline, threaded, or distributed execution.
```rust
use vv_agent::{Agent, ExecutionMode, ModelRef, Runner, RunConfig, VvLlmModelProvider};
#[tokio::main]
async fn main() -> Result<(), Box> {
let provider = VvLlmModelProvider::from_settings_file("local_settings.json")
.with_default_backend("deepseek");
let runner = Runner::builder()
.model_provider(provider)
.workspace("./workspace")
.build()?;
let agent = Agent::builder("assistant")
.instructions("You plan, use tools when useful, and call task_finish when done.")
.model(ModelRef::backend("deepseek", "deepseek-v4-pro"))
.build()?;
let result = runner
.run_with_config(
&agent,
"Create notes.md with three project takeaways.",
RunConfig::builder()
.max_cycles(12)
.execution_mode(ExecutionMode::Inline)
.build(),
)
.await?;
println!("{:?}", result.final_output());
Ok(())
}
```
Sessions keep conversation history across runner calls:
```rust
use vv_agent::{MemorySession, RunConfig};
let session = MemorySession::new("thread-001");
runner
.run_with_config(&agent, "Analyze the current workspace.", RunConfig::builder().session(session.clone()).build())
.await?;
let result = runner
.run_with_config(&agent, "Continue with follow-up suggestions.", RunConfig::builder().session(session).build())
.await?;
```
### Live Runs and Events
`Runner::run()` and `run_with_config()` are the one-shot entrypoints. Use
`Runner::start()` when an application needs live UI/server control: subscribe
to events, approve pending tools, cancel a run, or await the final result from
one `RunHandle`. `Runner::stream()` is a convenience wrapper over `start()` for
typed live events.
```rust
use vv_agent::{ApprovalDecision, RunConfig, RunEventPayload};
let handle = runner
.start(&agent, "Inspect the workspace and report findings.", RunConfig::default())
.await?;
let mut events = handle.events();
while let Some(event) = events.next().await {
match event?.payload() {
RunEventPayload::AssistantDelta { delta } => print!("{delta}"),
RunEventPayload::ToolCallStarted { tool_name, .. } => {
eprintln!("tool started: {tool_name}");
}
RunEventPayload::ApprovalRequested { request_id, .. } => {
handle.approve(request_id, ApprovalDecision::allow()).await?;
}
_ => {}
}
}
let result = handle.result().await?;
```
Each `RunEvent` is a v1 envelope with `event_id`, `run_id`, `trace_id`,
optional session and parent identifiers, timing, metadata, and a typed
`RunEventPayload`. `JsonlRunEventStore` can append events and replay a run,
including child events linked by parent run id.
Live tool approval uses `ApprovalProvider` and the handle-owned broker. The
model-facing `ask_user` tool remains for requesting user input as part of the
conversation. Host applications can also attach `ContextProvider` values for
ordered prompt fragments and `MemoryProvider` values for external search, save,
and compaction lifecycle hooks.
### App Server
Use the App Server when a product shell needs to drive `vv-agent` over a stable
JSON-RPC protocol instead of linking directly to runtime internals. It supports
stdio JSONL transport, thread and turn lifecycle requests, live item
notifications, approval server requests, replay, schema generation, and a typed
Rust test client.
```bash
vv-agent app-server --listen stdio
vv-agent app-server generate-json-schema --out target/app-server-schema/json
vv-agent app-server generate-ts --out target/app-server-schema/typescript
```
See `crates/vv-agent/docs/app_server.md` for protocol examples and client
responsibilities.
### Low-Level Runtime
Use the runtime directly only when you need to assemble the LLM client, prompt,
tool registry, workspace, and run controls yourself. New embedded applications
should start with `Agent` + `Runner`.
```rust
use std::path::PathBuf;
use vv_agent::config::build_vv_llm_from_local_settings;
use vv_agent::prompt::{build_system_prompt_with_options, BuildSystemPromptOptions};
use vv_agent::{build_default_registry, AgentRuntime, AgentTask, RuntimeRunControls};
fn main() -> Result<(), Box> {
let (llm, resolved) = build_vv_llm_from_local_settings(
"local_settings.json",
"deepseek",
"deepseek-v4-pro",
90.0,
)?;
let runtime = AgentRuntime::new(llm).with_tool_registry(build_default_registry());
let system_prompt = build_system_prompt_with_options(
"You are a reliable execution agent.",
BuildSystemPromptOptions {
language: "zh-CN".to_string(),
use_workspace: true,
enable_todo_management: true,
..BuildSystemPromptOptions::default()
},
);
let mut task = AgentTask::new(
"demo",
resolved.model_id,
system_prompt,
"Read the workspace README and summarize the project.",
);
task.max_cycles = 12;
let result = runtime.run_with_controls(
task,
RuntimeRunControls {
workspace: Some(PathBuf::from("./workspace")),
..RuntimeRunControls::default()
},
)?;
println!("{:?}: {:?}", result.status, result.final_answer);
Ok(())
}
```
See `crates/vv-agent/examples/01_quick_start.rs` for a complete low-level
runtime version with event logging.
## Core Capabilities
| Area | What `vv-agent` provides |
| --- | --- |
| Runtime | Multi-cycle model execution, explicit terminal states, live `RunHandle`, cancellation, typed events, event replay, and max-cycle handling. |
| Tools | Built-in tools plus a `ToolOrchestrator` path for policy, approval, dispatch, timeout, and telemetry. |
| SDK | `Agent`, `Runner`, `RunConfig`, `ModelSettings`, typed tools, `Agent::as_tool()`, `RunEvent`, providers, and `Session`. |
| Memory | Token budgeting, prompt-too-long retries, micro and full compaction, artifact-backed large tool results, image trimming, session memory, and external provider hooks. |
| Hooks | Rust `RuntimeHook` implementations can inspect or patch LLM calls, tool calls, memory compaction, and run lifecycle behavior. |
| Sub-agents | Runtime-backed sub-task creation, batch submission, background status polling, continuation, steering, and inherited streaming callbacks. |
| Skills | Skill directory discovery, frontmatter parsing, validation, prompt rendering with budget limits, activation, and activation history. |
| Workspace | Local, in-memory, and S3 object-store backends behind one `WorkspaceBackend` boundary. |
## Execution Backends
The public SDK selects scheduling through `ExecutionMode`. Lower-level runtime
backend structs remain available for advanced integrations:
| Backend | Use case |
| --- | --- |
| `ExecutionMode::Inline` | Default synchronous execution in the current process. |
| `ExecutionMode::Threaded` | Submit runs without blocking the caller. |
| `ExecutionMode::Distributed` | Checkpointed cycle execution with serializable runtime recipes and pluggable dispatch. |
Checkpointed runs can store state in memory, SQLite, or Redis. The optional
`apalis` feature adds an Apalis job bridge for applications that already use
Apalis workers:
```bash
cargo test -p vv-agent --features apalis --test apalis_backend
```
The distributed API also has an inline fallback, which is useful for local
development and tests. See `crates/vv-agent/examples/23_distributed_backend.rs`.
## Workspace Backends
All built-in file tools go through `WorkspaceBackend`. That keeps local files,
memory-backed files, and S3-compatible object storage on the same tool contract.
`list_files` and `workspace_grep` include safety defaults for large workspaces:
bounded result counts, hidden/dependency directory filtering, explicit ignored
path inclusion, and local `rg` acceleration when available.
## Examples
The numbered examples are the best way to explore the public API:
```bash
cargo run -p vv-agent --example 01_quick_start
cargo run -p vv-agent --example 03_sdk_client
cargo run -p vv-agent --example 04_session_api
cargo run -p vv-agent --example 23_distributed_backend
cargo run -p vv-agent --example 24_workspace_backends
cargo run -p vv-agent --example 26_agent_runner_facade
cargo run -p vv-agent --example 27_facade_handoff
cargo run -p vv-agent --example 28_facade_approval_background_trace
```
See `crates/vv-agent/examples/README.md` for the full example index covering
Agent + Runner, runtime hooks, custom tools, handoffs, live approval,
background tasks, tracing, sub-agent pipelines, skills, streaming, cancellation,
state stores, execution backends, workspace backends, and temporary tool
injection.
## Live Smoke Tests
Live tests are opt-in and use a local settings file without printing
credentials. By default they read the untracked
`crates/vv-agent/tests/dev_settings.json`; start from
`crates/vv-agent/tests/dev_settings.example.json`.
```bash
VV_AGENT_RUN_LIVE_TESTS=1 \
cargo test -p vv-agent --test live_deepseek -- --ignored
```
The live suite exercises direct runtime completion, SDK completion,
`ask_user`, todo updates, memory notes, skill activation, workspace tools,
image reading, foreground and background shell commands, sub-agent polling, and
configured sub-agent delegation.
## Verification
Run the standard checks from `vv-agent-rs/`:
```bash
cargo fmt --check
cargo test -p vv-agent
cargo check --examples
cargo clippy --all-targets --all-features -- -D warnings
```
Focused checks that are useful while editing public docs and examples:
```bash
cargo test -p vv-agent --test public_api
cargo test -p vv-agent --test examples_coverage
```
## Repository Layout
```text
vv-agent-rs/
Cargo.toml
crates/vv-agent/
src/
cli/ # CLI entrypoint and task construction
config/ # LLM settings loading and model resolution
llm/ # LLM trait, scripted test client, vv-llm client bridge
memory/ # compaction, artifacts, session memory, token budgeting
prompt/ # system prompt sections and prompt-cache metadata
agent.rs # public Agent builder
runner.rs # public Runner over runtime execution
run_config.rs
model.rs
model_settings.rs
sessions.rs
runtime/ # agent runtime, hooks, backends, cancellation, sub-agents
skills/ # skill discovery, parsing, validation, activation
tools/ # registry, schemas, dispatcher, built-in handlers
workspace/ # local, memory, and S3 workspace backends
examples/
tests/
docs/
```
Additional design notes live under `docs/`, especially `docs/architecture.md`
and `docs/model-settings.md`.