Expand description
§localharness — agents that own themselves
One Rust crate that’s both an agent SDK — streaming text, custom tools,
safety policies, background triggers, MCP, context compaction, all from a
single cargo add with zero external binaries — and (on wasm32 with
browser-app) the same loop compiled into a wallet-owning, self-sovereign
agent that runs in the browser.
§Quick start
use localharness::{Agent, GeminiAgentConfig};
let cfg = GeminiAgentConfig::new(std::env::var("GEMINI_API_KEY").unwrap())
.with_system_instructions("You are a concise code reviewer.");
let agent = Agent::start_gemini(cfg).await?;
let response = agent.chat("What is 2+2?").await?;
println!("{}", response.text().await?);
agent.shutdown().await?;§Layers
| Layer | Type | Purpose |
|---|---|---|
| 1 | Agent | High-level facade: connect, chat, shutdown. |
| 2 | Conversation / ChatResponse | Stateful session, multi-cursor streams. |
| 3 | connections::Connection | Transport abstraction. |
| aux | Filesystem | What the 8 fs-shaped built-in tools call into; swap the impl to target OPFS, an in-memory FS, etc. |
§Stability & MSRV
MSRV is Rust 1.85 (edition 2024); raising it is a minor-version bump. The 1.0
semver promise COVERS the agent-SDK surface: the layer seams (Agent + the
*AgentConfigs, Conversation/ChatResponse/ChatCursor,
connections::Connection/ConnectionStrategy); the extension traits
(tools::Tool/ToolRunner, hooks, policy, triggers); the wire-neutral
types (content, types, error::Error/Result, filesystem::Filesystem + the
8 fs builtins, the named builtins); and the root-re-exported backend
constructors + *BackendConfig/*Connection/*ConnectionStrategy.
NOT covered (may change in any release, semver-exempt): the wallet feature —
the entire registry surface is coupled to live on-chain diamond addresses +
facets that churn via diamondCut, plus wallet/tempo_tx; the per-backend
backends::*::{wire,api,compaction} modules; opaque history byte formats
(history_bytes/set_history_bytes); the browser-app app (wasm-only, private);
the local feature; and the platform compiler/runtime helpers (rustlite,
soliditylite, bashlite, raster, compose). Growable public structs/enums
carry #[non_exhaustive] (or grow only via ..Default::default()-friendly
fields) so additive changes stay non-breaking.
Re-exports§
pub use agent::Agent;pub use agent::AgentConfig;pub use agent::GeminiAgentConfig;pub use agent::MockAgentConfig;pub use agent::AnthropicAgentConfig;pub use agent::OpenAiAgentConfig;pub use backends::gemini::decode_transcript_bytes;pub use backends::gemini::GeminiBackendConfig;pub use backends::gemini::GeminiConnection;pub use backends::gemini::GeminiConnectionStrategy;pub use backends::mock::MockConnection;pub use backends::mock::MockConnectionBuilder;pub use backends::mock::MockConnectionStrategy;pub use backends::mock::MockRunners;pub use backends::mock::ScriptedTurn;pub use backends::anthropic::AnthropicBackendConfig;pub use backends::anthropic::AnthropicConnection;pub use backends::anthropic::AnthropicConnectionStrategy;pub use backends::anthropic::AnthropicRunners;pub use backends::openai::OpenAiBackendConfig;pub use backends::openai::OpenAiConnection;pub use backends::openai::OpenAiConnectionStrategy;pub use backends::openai::OpenAiRunners;pub use backends::mcp::McpBridge;pub use backends::mcp::McpClient;pub use backends::mcp::McpToolDecl;pub use connections::Connection;pub use connections::ConnectionStrategy;pub use content::Content;pub use content::Media;pub use content::MediaKind;pub use content::Part;pub use conversation::ChatCursor;pub use conversation::ChatResponse;pub use conversation::Conversation;pub use error::Error;pub use error::Result;pub use filesystem::DirEntry;pub use filesystem::EntryKind;pub use filesystem::Filesystem;pub use filesystem::Metadata;pub use filesystem::WalkEntry;pub use filesystem::NativeFilesystem;pub use hooks::HookContext;pub use hooks::HookRunner;pub use hooks::OnSessionEndHook;pub use hooks::OnSessionStartHook;pub use hooks::OperationContext;pub use hooks::PostToolCallHook;pub use hooks::PostTurnHook;pub use hooks::PreToolCallDecideHook;pub use hooks::PreTurnHook;pub use hooks::SessionContext;pub use hooks::TurnContext;pub use policy::allow_all;pub use policy::deny_all;pub use policy::enforce;pub use policy::evaluate;pub use policy::is_path_in_workspace;pub use policy::secure_normalize_path;pub use policy::workspace_only;pub use policy::AskUserHandler;pub use policy::Decision;pub use policy::Policy;pub use policy::Predicate;pub use tools::ClosureTool;pub use tools::Tool;pub use tools::ToolContext;pub use tools::ToolRunner;pub use triggers::every;pub use triggers::Trigger;pub use triggers::TriggerContext;pub use triggers::TriggerRunner;pub use types::BuiltinTool;pub use types::CapabilitiesConfig;pub use types::HookResult;pub use types::Step;pub use types::StepSource;pub use types::StepStatus;pub use types::StepTarget;pub use types::StepType;pub use types::StreamChunk;pub use types::SystemInstructions;pub use types::ThinkingLevel;pub use types::ToolCall;pub use types::ToolResult;pub use types::TranscriptEntry;pub use types::TranscriptRole;pub use types::TriggerDelivery;pub use types::UsageMetadata;
Modules§
- accounting
- Pure economics decision core for the Accounting (CFO / Treasurer) role of an
autonomous company (
design/autonomous-business/roles/accounting.md): a periodaccounting::Ledger(treasury + costs + earned revenue + SEED, held apart) plus pure judgements —accounting::net_position(signed, seed EXCLUDED),accounting::runway_cycles,accounting::breakeven_price,accounting::is_solvent/accounting::is_self_funding. Honest about the inherited “seed-capitalized, not self-funding” constraint. Native-testable, zero chain deps. Seesrc/accounting.rs. Pure economics decision core for the Accounting (CFO / Treasurer) role of an autonomous localharness company (design/autonomous-business/roles/accounting.md). It models the company’s books as DATA so the solvency / runway / break-even invariants run undercargo test: a [Ledger] is a period snapshot, every judgement is a pure function over it, and NOTHING here reads the chain, the meter, or a TBA balance — the wiring (registry::query_balance/check_balances/ the CreditMeterFacet read) lives in the deferred, greenlight-gated executor, exactly likework_cycle/keeper/lessons. - agent
- Layer-1 agent facade: connect, chat, shutdown.
Layer-1
Agentfacade. - backends
- Backend implementations (Gemini, MCP).
Backend implementations of the
Connectiontrait. - bashlite
- bashlite — a tiny, total, sandboxed shell that scripts the platform’s
filesystem in one pass (the cost unlock: a multi-step fs chore collapses
from N LLM rounds to ONE
execute_scripttool call). Native-testable core over abashlite::BashHosttrait. Seesrc/bashlite/+design/bashlite.md. bashlite — a tiny, deterministic, TOTAL shell that scripts the platform’s filesystem in ONE pass (seedesign/bashlite.md). - builtins
- The crate-wide built-in tool registry (fs tools, ask_question, finish,
call_agent, …) — backend-neutral; every backend registers from here.
Formerly
backends::gemini::tools(the re-export shim is gone). The crate-wide built-in tool registry — backend-NEUTRAL. - compose
- Compositor scheduling for
host::compose— the deferred-mutation module table (native-testable control flow). Seesrc/compose.rs. Compositor scheduling forhost::compose(roadmap Track A / Phase 1a) — the part that is pure control flow, so it lives here and is native-tested, independent of the wasmInstance/Memoryit will hold inapp::display. - confirm
- Pure typed-confirmation challenge gate for destructive tools
(native-testable,
turn_flowhoisting pattern): single-use random nonce bound to exact tool+args, valid only when typed by the USER. Enforced byapp::chat::confirm_guardat the dispatch layer. Seesrc/confirm.rs. Typed-confirmation challenge gate — the pure core of the destructive-action convention, enforced at the DISPATCH layer. - connections
- Transport abstraction traits. Transport abstraction.
- content
- Multimodal input primitives (text, images, documents, audio, video). Multimodal input primitives (text, images, documents, audio, video).
- conversation
- Stateful conversation session with multi-cursor streaming. Stateful conversation session.
- cut_
guard - Static safety lint for agent-authored facet cuts (SolidityLite §7 Layer 1):
reserved-selector denylist + clash +
_init==0. Pure + native-testable; wired intolocalharness facet cutas a pre-flight. Seesrc/cut_guard.rs. Static safety lint for agent-authored facet cuts — designsoliditylite.md§7 Layer 1, the “immune system” first line. - difficulty
- Pure DIFFICULTY ROUTER core (native-testable): classifies each chat turn
into a
difficulty::TurnTier(Light / Standard / Heavy) and maps it to a model preference +types::ThinkingLevel, so the in-tab agent can route cheap/minimal-thinking turns away from the premium tier reserved for build/debug. Wired intoapp::chatper-turn. Seesrc/difficulty.rs. Pure turn-DIFFICULTY classification — the in-tab “difficulty router” core. - docs_
manifest - THE single source of truth for the drift-prone FACTS mirrored across the
three managed docs (
web/skill.md,web/llms.txt,README.md): chain addresses (fromregistry::chain), the crate version,$LHpricing, the agent tool list, and the CLI command list.cargo run --bin gen-docsfills each doc’s<!-- GEN:key -->block from here; acargo testdrift gate + the release pre-flight enforce sync. Gated onwallet(it readsregistry::chain) ANDnot(wasm32): it only feeds the native gen-docs bin + the native drift test, so excluding it from the wasm build keeps the testnetMODERATOstrings (whichrender_chainsdocuments) out of the prod bundle — the last non-test wasm referencer ofMODERATO. Seedocs/SOP-doc-integrity.md. Single source of truth for the drift-prone FACTS that are mirrored across the managed docs (web/skill.md,web/llms.txt). The top-levelREADME.mdis hand-written and minimal — deliberately not generated. - encoding
- Pure hex / address / amount encoding helpers (native-testable). Hoisted out
of
app::eventsso they run undercargo test. Seesrc/encoding.rs. Pure hex / address / amount encoding helpers — native-testable, no DOM, no state, no async. - error
- Typed error hierarchy. Typed error hierarchy for the SDK.
- error_
codes - The one
LHxxxxerror-code registry (compile / runtime / tx-revert). The oneLHxxxxerror-code registry — a single source of truth spanning the three failure families an agent (or a user) hits on this platform: - evm_
tools - READ-ONLY multi-chain EVM tools (balances /
eth_call/ ENS) overregistry::multichain— registered by the browser chat session AND the headless CLIcall, so identifier resolution is real on both surfaces. Multi-chain EVM READ tools (Ethereum, Base, Optimism, Arbitrum, Polygon, Tempo): native/ERC-20 balances, ENS resolution, and a genericeth_call, so an agent reads OTHER chains directly instead ofweb_fetch-ing third-party explorer APIs. ALL READ-ONLY — no writes, no signing. Backed byregistry::multichain(curated CORS-enabled public RPCs). Returned chain data is UNTRUSTED. - filesystem
- Filesystem abstraction for built-in fs tools. Filesystem abstraction for the built-in fs tools.
- hiring
- Pure role-fit scoring core for the HR (People Ops / Recruiting) role of an
autonomous company (
design/autonomous-business/roles/hr.md): score + rank candidate agents against an open seat (hiring::RoleNeed) by exact role + proven reputation (hiring::score_candidate/hiring::rank_candidates). Ahiring::Candidatemirrors awork_cycle::WorkerState(with aFromimpl) and ranks the same waywork_cycle::assign_next_taskallocates, so HR ranking and work-cycle allocation agree. Native-testable. Seesrc/hiring.rs. Pure role-fit scoring core for the HR (People Ops / Recruiting) role of an autonomous localharness company (design/autonomous-business/roles/hr.md). Given a [RoleNeed] (the open seat: requiredwork_cycle::Role+ a minimum on-chain reputation bar) and a pool of [Candidate] agents, it decides who is ELIGIBLE and RANKS the eligible ones best-first. Pure functions over data, no chain / I/O — the wiring (reputation_ofreads,invite_to_guild/set_rolewrites) lives in the deferred executor, samekeeper/lessons/work_cyclepattern, so the eligibility + ordering invariants run undercargo test. - hooks
- Hook traits for observing and gating agent events. Hook traits and the runner that dispatches them.
- html_fb
- Pure HTML → framebuffer rasterizer (block-level text subset over the
rasterbitmap font; native-testable, zero web-sys). Hoisted out ofapp::display(roadmap R5). Seesrc/html_fb.rs. HTML → framebuffer rasterization (pure, native-testable). - keeper
- Pure decision core for a decentralized scheduler keeper (krafto feedback #1.5,
the P2P answer to the centralized Vercel cron): which due
ScheduleFacetjobs THIS keeper should fire this tick — deterministic fair assignment (no thundering herd) + rank-staggered backoff (liveness if a peer is offline). Native-testable, zero chain/P2P deps. Seesrc/keeper.rs. Pure decision core for a decentralized scheduler keeper (krafto #1.5): given the on-chain ScheduleFacet jobs + this peer’s roster position, decide which due jobs to fire this tick — herd-free (one primary per job) with backup liveness. No chain/P2P deps; the wiring is a thin shell (localharness keeper+ the proxy?poke). - kv_
reduce - Pure Last-Writer-Wins key/value CRDT for SessionRoom shared state (#22):
folds a set of decrypted ops into a converged map (order-independent,
idempotent, optional TTL). Native-testable. See
src/kv_reduce.rs. Last-Writer-Wins key/value CRDT for SessionRoom shared state (GitHub #22). - kv_room
- SessionRoom op sealing/opening + deterministic per-room key derivation (#22):
AES-256-GCM confidentiality under
K_roominside a writer-signed, room-boundsignaling_sealenvelope. Needswalletfor k256/keccak. Native-testable. Seesrc/kv_room.rs. SessionRoom op sealing + per-room key derivation (GitHub #22). - lessons
- Pure lessons-blob merging + prompt-section composition for the agent
LESSONS LOOP (native-testable). The browser
record_lessontool, the headless CLIcall, and the proxy scheduler worker all fold its output into the system prompt. Seesrc/lessons.rs. Self-recorded agent lessons — the native-testable core of the LESSONS LOOP. - policy
- Declarative tool-execution policy engine. Declarative tool-execution policy engine.
- push_
enroll - Pure Web Push enrollment-verification core (native-testable; telemetry
#40): confirm a POSTed push subscription actually LANDED in the proxy
store + compose the bell panel’s enrolled/not-enrolled status line.
Consumed by
app::notifications. Seesrc/push_enroll.rs. Pure Web Push enrollment-verification core (native-testable; telemetry #40). - raster
- Pure framebuffer rasterization +
Viewport(the host::compose geometry foundation; native-testable, used byapp::display). Seesrc/raster.rs. Pure, native-testable framebuffer rasterization with a viewport — the geometry foundation forhost::compose(roadmap Phase 0a,design/host- compose.md). - registry
- JSON-RPC client for the on-chain registry diamond.
JSON-RPC client for
LocalharnessRegistry— read AND write. - router
- Pure INTENT-ROUTER core (native-testable): classifies a chat message as
router::Route::Free(balance/UI-command/docs-FAQ — answered locally, zero$LH) orMetered(the normal ~1$LHmodel turn). Exact-allowlist conservative by contract;'!'always forces Metered. Therouter::IntentClassifiertrait is the seam a local-model classifier (in-browser Gemma) can slot into later. Wired inapp::chat::router_wire. Seesrc/router.rs. Pure INTENT-ROUTER core — the free/metered cost gate in front of the browser chat’s metered model call (native-testable, thecrate::turn_flowhoisting pattern: no DOM, no state, no async). - rustlite
- Rust-subset to wasm compiler.
- seed_
flow - Pure decision core for the seed-pull apex round-trip (native-testable):
only a return leg carrying an actual sealed seed repaints; an empty
?seed_import=nonebounce scrubs the URL without touching the painted face, and the apex bounces BACK in history (bfcache) when it has nothing to hand over. Wired inapp::seed_pull+app::mount. Seesrc/seed_flow.rs. Pure decision core for the seed-pull apex round-trip legs (native-tested; theturn_flowhoisting pattern). The wasm plumbing lives insrc/app/seed_pull.rs+ the mount routing insrc/app/mod.rs; THIS module owns the two decisions that used to cause a visible face repaint for every pure visitor: - sharedfs_
reconcile - Pure, deterministic CONVERGENT reconcile for cross-device shared-folder sync
(native-testable). Hoisted out of
app::sharedfs_syncso the convergence / symmetry property runs undercargo test. Seesrc/sharedfs_reconcile.rs. Pure, deterministic CONVERGENT reconcile for the cross-device shared-folder sync (crate::app::sharedfs_sync— cfg-gated out of non-browser doc builds, so plain code formatting here, not links). - signaling_
seal - Pure signed-envelope layer for on-chain WebRTC signaling blobs — the SDP
sealing/sender-authentication core (native-testable; needs
walletfor k256). Hoisted out ofapp::teams_syncso the seal/unseal round-trip and tamper/forgery rejection run undercargo test. Seesrc/signaling_seal.rs. Pure, native-testable envelope layer for on-chain WebRTC signaling blobs (the P2P teams layer’s SDP exchange overSignalingFacet.postSignal). - simulation
- PURE MULTI-CYCLE FORECAST core: runs
work_cycle::stepforward over N cycles from asimulation::SimConfigand projects the company’s trajectory — per-cyclesimulation::CycleSnapshots (treasury, throughput, net position) plus the runsimulation::Forecast(total accepted, runwaysimulation::Forecast::ran_out_at, finalaccounting::Ledger). Each cycle injects the off-core delivery at a fixed assumed quality, advances one transition, and books revenue/costs. Preview ONLY — executes/broadcasts NOTHING. Native-testable, zero chain deps. Seesrc/simulation.rs. PURE MULTI-CYCLE FORECAST core for an autonomous localharness company — runs thecrate::work_cycledriver forward over N cycles and projects the company’s TRAJECTORY (treasury, throughput, runway, the honest books) so an operator can SEE where the business is heading before committing real$LH. - skills
- Pure agent-skills blob (JSON array) upsert/remove + prompt-section
composition for the agent SKILLS LOOP (native-testable). The browser
create_skilltool, the headless CLIcall, and the proxy scheduler worker all fold its output into the system prompt. Seesrc/skills.rs. Agent-defined named skills — the native-testable core of the SKILLS LOOP. - soliditylite
- Solidity/EVM-subset to EVM-bytecode compiler foundation (the EVM analog of
rustlite): a bytecode assembler + worked dispatch/init scaffolding. Seedesign/soliditylite.md. SolidityLite — a hand-rolled, in-browser Solidity/EVM-subset → EVM-bytecode compiler (the EVM analog ofcrate::rustlite). This module is the FOUNDATION: a bytecode assembler ([asm]) plus a worked emitter that proves the dispatch/init scaffolding end-to-end against a deployable artifact. - subdomain
- Pure subdomain-name validation (native-testable) — the single source of
truth shared by the browser create tools and kept in sync with the
on-chain
LocalharnessRegistryFacet._isValidNamerule. Seesrc/subdomain.rs. Pure subdomain-name validation — the single source of truth for the browser create tools, kept in sync with the on-chainLocalharnessRegistryFacet._isValidNamerule. Native-tested (this is why it lives at the crate root, not inside the wasm-onlyappmodule). - tempo_
tx - Tempo Transaction (tx type 0x76) encoder for native account abstraction.
Tempo Transaction encoder (tx type
0x76). - tool_
params - Single-table tool parameters: the
tool_params!macro generates BOTH the typed args struct AND the Gemini-safe wireinput_schemafrom ONE table (schema↔parse drift impossible by construction; zero deps, wasm-clean). Migrated wasm-gated chat tools hoist their tables here (theturn_flowpattern) so plaincargo testbyte-checks their schemas. Opt-in per tool. Seesrc/tool_params.rs. Single-table tool parameters: ONEtool_params!declaration generates BOTH the typed args struct AND the wireinput_schemaJSON, so schema↔parse drift is impossible by construction — a field cannot exist in the schema without existing in the struct, and vice versa. - tools
- Custom tool registration and dispatch. Host-side custom tools.
- triggers
- Background triggers that push messages into the agent. Background triggers — fire-and-forget tasks that push messages into the agent. Each trigger runs in its own tokio task; the runner owns the task handles and aborts them on shutdown.
- turn_
flow - Pure turn-outcome classification for the continuous-execution chat loop
(native-testable). Hoisted out of
app::chatso its guard tests run undercargo test. Seesrc/turn_flow.rs. Pure turn-outcome classification for the in-tab agent’s continuous-execution loop — native-testable, no DOM, no state, no async. - turn_
stage - Pure state machine for the turn-stage micro-pipeline (“paying → thinking
→ streaming”) shown inside a pending assistant turn (native-testable,
same hoisting pattern as
turn_flow). Seesrc/turn_stage.rs. Pure state machine for the turn-stage micro-pipeline — the terse “paying → thinking → streaming” line shown inside a PENDING assistant turn (GitHub #19: the $LH-payment → execution transition was opaque; a visitor paid and then stared at an unexplained pause). - types
- Public boundary types (steps, tool calls, usage, config, etc.). Public boundary types for the SDK.
- wallet
- Secp256k1 keypair, BIP-39 mnemonics, and RLP encoding. In-browser secp256k1 keypair — k256 + sha3 directly.
- work_
cycle - Pure work-cycle decision core for an autonomous company of role-agents
(
design/autonomous-business/): allocate a funded task to the best-fit role-agent, judge the delivered result, pay the worker, and attest the outcome — modeling one claim→work→judge→pay→attest cycle as DATA (every side effect is anwork_cycle::Actiondescriptor the caller maps onto a realregistrybounty/x402/attest call). Native-testable, zero chain deps. Seesrc/work_cycle.rs. Pure work-cycle decision core for an autonomous localharness company — the logic by which a founded org actually DOES work: allocate a funded task to the best-fit role-agent, judge the delivered result, pay the worker, and attest the outcome to reputation. It models ONE claim → work → judge → pay → attest cycle (the oggoel / agent-coordination flywheel) as DATA: every decision is a pure function and every side effect is an [Action] descriptor the caller later maps onto a real edge call (registry::post_bounty_sponsored/claim_bounty_sponsored/accept_result_sponsored/attest_sponsored/ a TBA$LHtransfer). - work_
cycle_ runtime - PURE PLANNING SHELL over
work_cycle: awork_cycle_runtime::Reader(noregistry/walletdep) feeds the read-only company view intowork_cycle_runtime::plan_cycle, which runswork_cycle::stepto quiescence and returns awork_cycle_runtime::CyclePlanof WHAT WOULD HAPPEN — preview ONLY, executes/broadcasts NOTHING. The greenlight-gated executor that maps each plannedwork_cycle::Actiononto its sponsoredregistrycall is deferred. Native-testable. Seesrc/work_cycle_runtime.rs. PURE PLANNING SHELL around thecrate::work_cycledecision core — turns a read-only view of the company (its backlog, its role-agents, its treasury) into a [CyclePlan] describing WHAT THE NEXT CYCLE WOULD DO, without ever executing or broadcasting anything. - x402_
hook - App-injected x402 payment-signing hook (lets the backend
call_agenttool sign payments using the app-layer wallet). App-injected x402 hooks.
Macros§
- tool_
params - Generate a typed tool-args struct + its wire
input_schemafrom ONE table.