Provider choice
Great agents.
Your choice of model.
A provider interface keeps model configuration separate from your agent. Connect a service, use a local model, or implement your own provider.
Explore providersForge
An open runtime with identity, tools,
and accountability built in.
The runtime takes shape around a common contract.
Six languages. One open contract. Yours to build on.
Inside the runtime
Identity, capability, tools, and lifecycle.
Explore the contracts beneath the agent.
Illustrated architecture. Select a layer.
An OAS identity binds the runtime to its lineage. The agent carries a verifiable origin into the work it performs.
OAS identity · signed lineage
Explore identityThe SDK
Rust, TypeScript, Go, Python, Swift, and Kotlin.
A common contract, expressed in the language you love.
Start with an identity. Add a provider and the tools your agent needs. Keep the same foundations as your project grows.
Meet the SDKs//! Forge SDK Quickstart -- Rust
//!
//! This example demonstrates the complete Forge agent lifecycle:
//!
//! 1. Create a Human Root (HMR) identity
//! 2. Derive an agent identity from the HMR
//! 3. Configure a mock language model provider
//! 4. Register tools in the tool registry
//! 5. Run the agent's tool loop
//! 6. Print the result including the agent's OAS DID
//!
//! No API keys are required. The mock provider returns deterministic
//! responses for demonstration purposes.
…//! Forge SDK Quickstart -- Rust
//!
//! This example demonstrates the complete Forge agent lifecycle:
//!
//! 1. Create a Human Root (HMR) identity
//! 2. Derive an agent identity from the HMR
//! 3. Configure a mock language model provider
//! 4. Register tools in the tool registry
//! 5. Run the agent's tool loop
//! 6. Print the result including the agent's OAS DID
//!
//! No API keys are required. The mock provider returns deterministic
//! responses for demonstration purposes.
use std::sync::Arc;
use forge_sdk::prelude::*;
// ---------------------------------------------------------------------------
// Step 1: Mock Language Model
// ---------------------------------------------------------------------------
//
// In production, you would use a real provider like "openai:gpt-4o" or
// "anthropic:claude-sonnet-4-5-20250929". For this quickstart, we implement
// a mock that simulates a two-step interaction:
//
// Turn 1: The model requests the "get_weather" tool.
// Turn 2: The model produces a final text response using the tool result.
struct MockModel;
#[async_trait]
impl LanguageModel for MockModel {
fn model_id(&self) -> &str {
"mock:quickstart-v1"
}
fn provider_namespace(&self) -> &str {
"mock"
}
fn supports_tool_calling(&self) -> bool {
true
}
async fn generate(
&self,
messages: &[ModelMessage],
tools: &[ToolDefinition],
_options: &GenerateOptions,
) -> ForgeResult<GenerateResult> {
// Count assistant messages to determine which turn we are on.
let assistant_count = messages
.iter()
.filter(|m| m.role() == Role::Assistant)
.count();
if assistant_count == 0 && !tools.is_empty() {
// Turn 1: Request the "get_weather" tool.
let tool_call_msg = ModelMessage::tool_call(
"call_001",
"get_weather",
serde_json::json!({"city": "San Francisco"}),
);
Ok(GenerateResult {
message: tool_call_msg,
finish_reason: FinishReason::ToolCalls,
usage: Usage {
prompt_tokens: 50,
completion_tokens: 20,
total_tokens: 70,
},
})
} else {
// Turn 2: Produce a final text response.
let response_msg = ModelMessage::text(
Role::Assistant,
"Based on the weather data, San Francisco is currently 65 degrees \
Fahrenheit with partly cloudy skies. A great day to be outside!",
);
Ok(GenerateResult {
message: response_msg,
finish_reason: FinishReason::Stop,
usage: Usage {
prompt_tokens: 80,
completion_tokens: 30,
total_tokens: 110,
},
})
}
}
}
// ---------------------------------------------------------------------------
// Step 2: Tool Executor
// ---------------------------------------------------------------------------
//
// Tools are the agent's interface to the external world. Each tool has a
// definition (name, description, parameters, tier) and an executor function.
async fn handle_get_weather(args: serde_json::Value) -> Result<String, String> {
let city = args
.get("city")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
// In production, this would call a real weather API.
Ok(format!(
"Weather in {city}: 65F, partly cloudy, humidity 72%, wind 8 mph SW"
))
}
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
#[tokio::main]
async fn main() {
println!("=== Forge SDK Quickstart (Rust) ===\n");
// -----------------------------------------------------------------------
// Step 3: Create the identity hierarchy
// -----------------------------------------------------------------------
//
// Every Forge agent carries an OAS DID (Decentralized Identifier) from
// birth. The identity hierarchy starts with a Human Root (HMR) and agents
// are derived from it via HKDF key derivation.
let hmr = create_hmr_identity("l1fe", "alice")
.expect("HMR identity creation should succeed");
println!("HMR identity created:");
println!(" DID: {}", hmr.did());
println!(" Lineage depth: {}", hmr.lineage_depth());
println!();
let agent_identity = derive_agent_identity(&hmr, "weather-assistant", "l1fe")
.expect("Agent identity derivation should succeed");
println!("Agent identity derived:");
println!(" DID: {}", agent_identity.did());
println!(" Lineage depth: {}", agent_identity.lineage_depth());
println!();
// -----------------------------------------------------------------------
// Step 4: Build the tool registry
// -----------------------------------------------------------------------
//
// Tools are classified into three immutable tiers per the ANVIL spec:
// Tier 1 (Platform): Always available inside the sandbox.
// Tier 2 (Host): Outside the sandbox; requires Arsenal ACT authorization.
// Tier 3 (Embedded): Custom logic compiled into the agent's WASM module.
let weather_tool = ToolDefinition::builder("get_weather")
.description("Get the current weather for a city")
.tier(ToolTier::Host)
.build();
let mut registry = ToolRegistry::new();
registry.register(
weather_tool,
FnToolExecutor::new(|call| {
Box::pin(async move { handle_get_weather(call.arguments().clone()).await })
}),
);
println!("Tool registry: {} tool(s) registered", registry.len());
println!();
// -----------------------------------------------------------------------
// Step 5: Configure and run the agent
// -----------------------------------------------------------------------
let model: Arc<dyn LanguageModel> = Arc::new(MockModel);
let approval: Arc<dyn ApprovalHandler> = Arc::new(AutoApprove);
let config = AgentConfig::new("weather-assistant", "mock:quickstart-v1")
.with_system_prompt("You are a helpful weather assistant. Use the get_weather tool to answer questions.")
.with_identity(agent_identity)
.with_max_steps(5);
let agent = ToolLoopAgent::new(config, model, registry, approval);
println!("Running agent tool loop...\n");
match agent.run("What is the weather in San Francisco?").await {
Ok(output) => {
// ---------------------------------------------------------------
// Step 6: Print the results
// ---------------------------------------------------------------
println!("--- Agent Output ---");
println!("Final text: {}", output.final_text);
println!("Steps taken: {}", output.steps_taken);
println!("Total tokens: {}", output.usage.total_tokens);
println!("Messages: {}", output.messages.len());
println!();
// Print the agent's DID from the config
println!("--- Agent Identity ---");
println!("Agent DID: {}", agent.config().agent_did().unwrap_or("(none)"));
println!("Lifecycle: {:?}", agent.lifecycle());
println!();
// Print health profile
let health = agent.health();
println!("--- Health Profile ---");
println!("Tool calls: {}", health.tool_invocations);
println!("Inferences: {}", health.inference_tokens);
}
Err(e) => {
eprintln!("Agent execution failed: {e}");
std::process::exit(1);
}
}
println!("\n=== Quickstart complete ===");
}
Snapshot of examples/rust/quickstart/src/main.rs. These examples use a mock provider. Follow the language guide for setup; the website does not execute them.
cd examples/rust/quickstartDifferent languages. Shared foundations. ANVIL defines eight contracts: identity, capability, tools, health, communication, collaboration, lifecycle, and telemetry.
Explore ANVILIdentity at the foundation
An agent should be able to show where it came from. And exactly what it has permission to do.
Forge brings OAS identities, signed lineage, and Arsenal capabilities into the runtime. Delegation carries its history. Authority has a boundary.
Discover agent identityTools with boundaries
Three tool tiers. Three distinct boundaries.
Choose a tier to see where it belongs.
Illustrated tool boundary. No request is executed.
External tools cross the agent boundary. Configure Arsenal ACTs to check invocations against granted scopes, and connect telemetry to inspect their results.
web.fetch(url)db.query(sql)fs.read(path)gh.create_pr()slack.post()stripe.charge()Stay in control
Choose the intelligence. Understand the state.
Follow the work, from action to evidence.
Provider choice
A provider interface keeps model configuration separate from your agent. Connect a service, use a local model, or implement your own provider.
Explore providersExplicit lifecycle
Initialization, ready, running, paused, error, and terminated. Defined transitions give the work a structure you can inspect.
Explore the lifecycleTelemetry and audit
OpenTelemetry-compatible spans and signed audit-trail primitives make execution inspectable.
Follow the evidenceArchitecture illustrations. No models, lifecycle transitions, or audit events are running on this page.
The developer experience
A place to build. A way to inspect.
Tools for the work around the agent.
Explore the command-line workflow and its implementation status.
A visual authoring workbench in development.
An operations console for durable workflows, in development.
Conceptual tool illustrations. Explore each guide for implementation and usage details.
Made to move
Explore WASM and WASI deployment, from local execution to hosted runtimes. Carry the contract with you, and check the requirements of each destination.
Find your deployment pathOpen by design
Read the contracts. Explore the implementation.
Build something the rest of us can build on.