Build verifiable, interactive AI agents in Rust, powered by NVIDIA Nemotron free LLM models.
A corrosive agent has a name, a version, and a set of active capabilities β all loadable from a JSON manifest β plus native Skills, MCP (Model Context Protocol) servers, and an Ed25519 identity so anyone can verify it with public-key cryptography. Serve it over a Tokio REST API, WebSocket, or gRPC, and give it memory with Pinecone, Qdrant, or any custom vector store.
| ποΈ Builder pattern | Fluent Agent::builder()β¦build() construction with semver + config validation |
| π JSON manifests | Load name/version/capabilities/skills/MCP servers from a file |
| π Verifiable identity | Ed25519 manifests; did:key DIDs; X.509 certs; key rotation & revocation (TrustStore) |
| π§ NVIDIA Nemotron | Chat, streaming, tool calling, embeddings β with retry/backoff + rate-limit handling |
| π οΈ Skills | Async JSON abilities with a sandbox: allowlists, permissions, timeouts, panic isolation |
| π Tool loop | chat_with_tools: the model auto-invokes skills; usage accounting hooks built in |
| π MCP | stdio + streamable-HTTP/SSE transports; tools, resources, and prompts |
| π Transports | REST + WebSocket + gRPC, with API-key/JWT auth, TLS, graceful shutdown, /ready, OpenAPI |
| π€ A2A delegation | RemoteAgent peers with pinned-key/DID verification; delegate chat & skills |
| πΎ Sessions | Pluggable SessionStore: in-memory, SQLite, or Redis persistence |
| π Vector stores | In-memory, Qdrant, Pinecone, pgvector; metadata filters, chunking, remember/recall |
π New to the library? Read the tutorial β it walks
from an empty project to a production-shaped agent, and ships on
docs.rs as the tutorial module.
[dependencies]
corrosive_agents = "0.0.1" # REST + WebSocket by default
tokio = { version = "1", features = ["full"] }Optional features:
corrosive_agents = { version = "0.0.1", features = ["full"] } # everything| Feature | Default | Enables |
|---|---|---|
server |
β | REST + WebSocket serving + auth middleware |
grpc |
β | gRPC serving + generated client (tonic) |
tls |
β | TLS helpers for REST and gRPC |
openapi |
β | OpenAPI 3 document at /openapi.json |
x509 |
β | X.509 certificate-based identity |
pinecone |
β | Pinecone vector store backend |
qdrant |
β | Qdrant vector store backend |
pgvector |
β | PostgreSQL/pgvector vector store backend |
sqlite-sessions |
β | SQLite-persisted conversation history |
redis-sessions |
β | Redis-persisted conversation history |
full |
β | All of the above |
Get a free API key at build.nvidia.com and export
it as NVIDIA_API_KEY.
use corrosive_agents::prelude::*;
#[tokio::main]
async fn main() -> Result<()> {
let agent = Agent::builder()
.name("research-agent")
.version("0.1.0")
.description("A concise research assistant")
.system_prompt("Answer in at most three sentences.")
.model(models::NEMOTRON_3_NANO_30B)
.capability(Capability::new("chat", "Conversational Q&A"))
.llm(NvidiaClient::from_env()?)
.generate_identity() // manifest is signed at build()
.build()?;
let reply = agent.chat("session-1", "What is NVIDIA Nemotron?").await?;
println!("{reply}");
Ok(())
}{
"name": "manifest-agent",
"version": "1.0.0",
"model": "nvidia/llama-3.3-nemotron-super-49b-v1",
"capabilities": [{ "name": "chat", "description": "Conversational Q&A" }],
"skills": ["word_count"],
"mcp_servers": [
{ "name": "fs", "command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] }
]
}use corrosive_agents::prelude::*;
# fn skill_impl() -> FnSkill { FnSkill::new("word_count", "", |i| async move { Ok(i) }) }
# async fn run() -> Result<()> {
let agent = AgentBuilder::from_json_file("agent.json")?
.skill(skill_impl()) // implementations bind to declared names
.llm(NvidiaClient::from_env()?)
.generate_identity()
.build()?;
agent.connect_mcp_servers().await?; // spawn + handshake declared MCP servers
let tools = agent.mcp_tools("fs").await?;
# Ok(())
# }use corrosive_agents::prelude::*;
# fn main() -> Result<()> {
let agent = Agent::builder()
.name("trusted").version("1.0.0")
.generate_identity()
.build()?;
// Ship the manifest anywhere as JSONβ¦
let json = agent.manifest().to_json()?;
// β¦and anyone can verify it, offline:
let received = AgentManifest::from_json(&json)?;
received.verify()?; // embedded public key
received.verify_with(&agent.public_key().unwrap())?; // or a pinned key
# Ok(())
# }Tampering with any signed field makes verification fail.
use std::sync::Arc;
use corrosive_agents::prelude::*;
# async fn run() -> Result<()> {
# let agent = Agent::builder().name("a").version("1.0.0").build()?;
let agent = Arc::new(agent);
// REST + WebSocket (feature `server`, on by default)
agent.clone().serve("0.0.0.0:8080".parse().unwrap()).await?;
// gRPC (feature `grpc`)
// agent.serve_grpc("0.0.0.0:50051".parse().unwrap()).await?;
# Ok(())
# }REST endpoints: GET /health, GET /agent, GET /agent/manifest,
GET /capabilities, GET /skills, POST /skills/{name}, POST /chat,
POST /verify, and a WebSocket at /ws with optional streamed chunks.
gRPC service (proto/agent.proto): GetInfo, Chat, ChatStream
(server streaming), ExecuteSkill β a generated Rust client ships with the
crate at corrosive_agents::grpc::pb::agent_service_client::AgentServiceClient.
use corrosive_agents::prelude::*;
use serde_json::json;
# async fn run() -> Result<()> {
let nvidia = NvidiaClient::from_env()?;
let agent = Agent::builder()
.name("rag").version("0.1.0")
.llm(nvidia.clone())
.embeddings(nvidia) // NvidiaClient embeds too
.vector_store(InMemoryVectorStore::new()) // or QdrantStore / PineconeStore
.build()?;
agent.remember("Nemotron models are free at build.nvidia.com", json!({"topic": "nvidia"})).await?;
let hits = agent.recall("where are Nemotron models hosted?", 3).await?;
# Ok(())
# }Bring your own store by implementing the VectorStore trait (three async
methods: upsert, search, delete).
| Example | Shows | Run |
|---|---|---|
build_agent |
Builder pattern, capabilities, skills, signed manifest, chat | cargo run --example build_agent |
agent_from_json |
Loading an agent + MCP config from examples/agent.json |
cargo run --example agent_from_json |
interactive_chat |
Terminal REPL with streamed tokens | cargo run --example interactive_chat |
tool_calling |
Model auto-invokes skills (function calling) + usage hooks | cargo run --example tool_calling |
sign_and_verify |
Public-key verification end to end (offline) | cargo run --example sign_and_verify |
vector_rag |
Embeddings + vector store + retrieval-augmented answers | cargo run --example vector_rag |
serve |
REST + WebSocket server | cargo run --example serve |
serve_grpc |
gRPC server | cargo run --example serve_grpc --features grpc |
a2a_delegation |
Agent-to-agent delegation with DID-pinned peer verification (offline) | cargo run --example a2a_delegation |
All LLM examples need NVIDIA_API_KEY (or NVIDIA_KEY in a .env file).
Constants in corrosive_agents::llm::models, all usable with a free key:
nvidia/nemotron-3-ultra-550b-a55b,nvidia/nemotron-3-super-120b-a12b,nvidia/nemotron-3-nano-30b-a3b(default)nvidia/llama-3.1-nemotron-ultra-253b-v1,nvidia/llama-3.3-nemotron-super-49b-v1,nvidia/llama-3.1-nemotron-nano-8b-v1,nvidia/nemotron-mini-4b-instruct- Embeddings:
nvidia/nv-embedqa-e5-v5,nvidia/llama-nemotron-embed-1b-v2
The catalog evolves β list what your key can reach with
GET https://integrate.api.nvidia.com/v1/models.
cargo test --features full # unit + integration + doc tests
cargo clippy --all-targets --features full
cargo fmt --check
cargo deny check # advisories, licenses, bans, sources (deny.toml)
cargo llvm-cov --features full # code coverage report
cargo run --manifest-path tools/protogen/Cargo.toml # regen gRPC code after editing proto/Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.