Repository navigation
Releases: oops-rs/mentra
Release list
Mentra 0.34.1
Mentra 0.34.1 ships with mentra-provider 0.9.6.
- Shell scheduling reads the fixed execution category without constructing and discarding its JSON schema. An optimized trait-dispatch probe measured 41 allocations per category lookup before the change and zero afterward, with unchanged probe executable size. This is a focused method measurement, not an end-to-end agent benchmark.
- ToolContext and ParallelToolContext expose an owned ToolProgress handle for work that outlives its tool call. Updates retain tool-call identity and stay transient (issue #67).
- The provider requires patched Tokio 1.53.3 and zstd 0.14.3. Mentra now requires provider 0.9.6, allowing downstream applications to resolve the fixed compression stack (issue #70).
- Approval previews, shell execution, and scheduling categories are preserved; the shell descriptor/category contract is covered by a regression test (issue #71).
Validation: Rust 1.88 MSRV, formatting, Clippy, all-feature and no-default tests, documentation, advisory checks, and both package archives passed locally. The compression HTTP roundtrip and allocation ablations passed.
mentra 0.28.0 / mentra-provider 0.9.0
Removed the RegisteredProvider alias
- Breaking:
mentra_provider::RegisteredProvideris removed. It was a bare
pub use Provider as RegisteredProvider;with no callers outside the crate's
own provider impls; useProvider.
Folded ModelCatalog and ProviderSessionFactory into Provider
- Breaking: the
ModelCatalogandProviderSessionFactorytraits are
removed;list_modelsandcreate_sessionare now required methods on
Provideritself. Every implementor in the workspace already implemented all
three traits on the same type, and neither trait was ever used as adyntype
or a generic bound. External implementors merge their two impl blocks into
theirProviderimpl.
Removed the unread RetryPolicy provider config
- Breaking:
mentra::RetryPolicy/mentra_provider::RetryPolicyand the
ProviderDefinition::retryfield are removed. No code in the workspace ever
read the policy; per-run retry behavior is configured with
RunOptions::provider_retry(mentra::runtime::ProviderRetry) and is
unchanged. SerializedProviderDefinitionJSON carrying aretrykey still
deserializes (the key is ignored).
Removed two unused OAuth credential-source constructors
- Breaking (feature
openai-oauth):
OpenAIOAuthCredentialSource::from_default_persistent_storeand
::from_default_persistent_store_or_authorizeare removed. Both were
one-line defaults with no callers; passPersistentTokenStoreKind::Autoto
from_persistent_store/from_persistent_store_or_authorizefor the
identical behavior.
Removed the test-only MemoryTokenStore
- Breaking (feature
openai-oauth):mentra::auth::openai::MemoryTokenStore
is removed. Nothing in the crate constructed it outside its own unit test; the
in-memory store now lives in that test module. TheTokenStoretrait stays
public, so an in-memory store is a few lines to write.
Removed the duplicate provider::model re-export module
- Breaking:
mentra::provider::modelis removed. Every item it re-exported
is already re-exported one level up atmentra::provider::*(and at
mentra::provider_core::*); import from there instead.
Builtin providers are constructor functions, not forwarding types
- Breaking: the seven forwarding wrapper types in
mentra::providerare
removed:openai::OpenAIProvider,openrouter::OpenRouterProvider,
anthropic::AnthropicProvider,gemini::GeminiProvider,
openai_compatible::OpenAiCompatibleProvider,ollama::OllamaProviderand
lmstudio::LmStudioProvider. Each held a singleArc<dyn Provider>and
forwarded every trait method to it verbatim. - Free functions returning
Arc<dyn Provider>replace them, with the same
arguments and the same resulting descriptor and capabilities:
openai::provider,openai::with_credential_source,
openai::with_shared_credential_source,openrouter::provider,
anthropic::provider,gemini::provider,openai_compatible::new,
openai_compatible::without_credentials,ollama::provider,
ollama::with_base_url,lmstudio::provider,lmstudio::with_base_url. Provideris now implemented forArc<dyn Provider>, so the results go
straight intoRuntimeBuilder::with_provider_instanceand
Runtime::register_provider_instanceas before.- Behavior change (Anthropic, Gemini): the removed
AnthropicProviderand
GeminiProviderwrappers did not forwardcompact, so provider-native
history compaction always failed withUnsupportedCapabilityand the
compaction engine silently fell back to local summarization even though both
providers advertisesupports_history_compaction. Without the wrappers the
compactcall now reaches the real provider, so runtimes built with
with_anthropic/with_geminicompact remotely under
CompactionMode::PreferRemoteand reportCompactionExecutionMode::Remote
where they previously reportedLocal. SetCompactionMode::LocalOnly(the default) to keep
the old behavior.
Agent state no longer carries an empty compaction key
- The always-empty
CompactionStateplaceholder is gone from
AgentMemoryStateand from thestate.json/ SQLite state payload. Agent
state written by older versions still loads; state written now cannot be
read by an older build.
Removed the unused SearchRequest conversion struct
- Breaking:
mentra::memory::SearchRequestis removed. Nothing
constructed it; every caller builds aMemorySearchRequestdirectly. MemoryEngine::searchnow takesMemorySearchRequestby value instead of
impl Into<MemorySearchRequest>.
Removed the never-read MemorySearchRequest::mode knob
- Breaking:
mentra::memory::MemorySearchModeand the
MemorySearchRequest::modefield are removed. NoMemoryStore
implementation ever branched on the value, so search results are unchanged.
Removed unreachable McpServerStatus variants
- Breaking:
McpServerStatus::Disconnectedand::Connectingare removed
from thementra::McpServerStatusre-export. Nothing ever constructed them:
list_serversreportsConnectedfor a live server andErrorfor a name
that only failed to connect, and a disconnected server is dropped from the
listing rather than reported. Out-of-repomatcharms on those variants must
be deleted.
MCP clients share one dispatch mechanism
McpBridgedTool::newis no longer generic over the transport; it takes
Arc<dyn McpToolClient>. Call sites passing a concreteArc<McpStdioClient>
orArc<McpSseClient>are unaffected, because theArccoerces at the
argument position.- The sealed
McpToolClienttrait gains ashutdownmethod, replacing the
manager's private transport enum. The trait is sealed, so no out-of-crate
implementor exists to update.
Resumed sessions can opt into a different runtime namespace
SessionResumeOptions::runtime_identifierlets a host rehome a legacy or
renamed-workspace session on its next persist.Nonekeeps the stored tag;
Some(id)replaces it for that resumed session without retagging other
agents or changing the shared runtime's identifier
(#59).- Source-breaking: exhaustive
SessionResumeOptionsstruct literals must
addruntime_identifier: Noneor use..Default::default().
Removed unused PermissionRequest type
- Source-breaking: the public
mentra::PermissionRequeststruct is removed.
Nothing produced or consumed it; the live path is the
SessionEvent::PermissionRequestedvariant and its inline fields.
Removed duplicate SubagentHandle::task_id
- Source-breaking:
SubagentHandle::task_idis removed. It always held the
same value asagent_id, which is the identifier reported as thetask_id
of the subagent'sSessionEvent::TaskUpdatedevents.
Removed unused CancellationFlag alias
- Source-breaking: the
mentra::runtime::CancellationFlagtype alias is
removed; usementra::runtime::CancellationToken, which it aliased.
Removed unused compaction type aliases
- Source-breaking: the
mentra::agentaliasesContextCompactionConfig,
ContextCompactionTriggerandContextCompactionDetailsare removed; use
CompactionConfig,CompactionTriggerandCompactionDetails. The persisted
context_compactionfield name keeps working through its serde alias.
mentra 0.20.0
mentra 0.20.0. mentra-provider is unchanged since 0.6.0 and is not part of this release.
Breaking
SessionEvent::PermissionRequestedgains aclassificationfield, so a pattern without a trailing.., or a literal constructing the variant, stops compiling.McpSseLimitsgainsmax_tools, so an exhaustive struct literal needs..Default::default().ToolDefinition/ToolExecutorare now implemented forBox<T>. BecauseBoxis#[fundamental], a downstream crate that wrote its ownimpl ToolDefinition for Box<ItsOwnTool>now collides — the hand-written forwarding these impls exist to replace.
Behavioral
SessionEvent::MemoryUpdatednow actually fires; it had never been emitted by any released version. A failed memory ingest surfaces as aNoticewithNoticeSeverity::Warning.
SessionEvent::MemoryUpdated is emitted at last
- The variant had been public since April while nothing sent it. The bridge
translating the runtime'sMemoryIngestFinishedinto it was implemented and
tested from the start but registered nowhere, because the only hook list in
sight was the runtime's shared one — where a bridge holding one session's
channel would forward every agent's memory activity to whichever session
installed it. - The correct place existed all along: every session is already built on its
ownRuntimeHandleclone, and eachwith_*step rebuilds that clone's
MemoryEnginefrom the hook list the clone carries. The bridge is now
appended to that per-session list increate_session*andresume_session*,
so a session's stream carries the memory events of exactly its own agents —
the session's agent and the subagents it spawns — and no other session's. - Behavior change for hosts: streams that never carried these events now do.
A successful ingest arrives asMemoryUpdated { agent_id, stored_records }
(includingstored_records: 0for an ingest with nothing new to store), and
a failed ingest as aNoticewithWarningseverity.
The other two MCP transports get the same pagination fixes
- Review found the
tools/listpage-cap off-by-one and the unbounded tool
accumulation in the new Streamable HTTP client and noted both were copied
from the older code. They were: the stdio and legacy HTTP+SSE clients carried
the identical two bugs, so fixing only the newest transport would have left
the two that ship today wrong. - All three now check the page cap only when another page is actually asked
for, so a list exactlymax_tool_pageslong is accepted rather than refused
for reaching the limit it may reach — and a cap of1no longer rejects
every server alive. All three bound the total number of advertised tools
(max_tools, defaulting to 4096), which the page and per-page byte caps
never did. - Breaking:
McpSseLimitsgains amax_toolsfield, so an exhaustive
struct literal needs..Default::default().
A permission request names the lane a call will actually run in
ToolClassification::execution_categoryreported the category a tool's
descriptor declares, while the scheduler asks the tool with the call's
input and then coerces a terminal tool out of a parallel lane. Every preview
builder in the tree copied the static value, so the two could disagree — and
they already did on a builtin:filesdeclares an exclusive mutation and
reports a parallel read for a batch that only reads.- In-tree that direction was conservative. The mirror shape is not, and it is
the one a host will write: a tool declaringReadOnlyParallelwhile
returning a mutating category fromexecution_category(input)was reported
to the host as read-only-parallel while the runtime scheduled a mutation, so
a host auto-approvingReadOnlyParallelauto-approved it. - The authorization path now reads the scheduler's own answer rather than the
descriptor's, which fixes every tool at once instead of the preview builders
that remember to. Found by adversarial review of the field as it landed.
The Streamable HTTP transport survives the servers it will meet
Adversarial review of the transport as it landed turned up ten defects. The
two that mattered most were both reachable by an ordinary misbehaving server,
and both traced to the same gap: the test fixture could not produce a server
that stalls, so neither could be written as a test.
- A notification's response body was drained outside the deadline wrapping its
POST.send()resolves on the response head and the body streams lazily, so
a server that promised a body and then went quiet left that drain waiting
forever — insideconnect, whichRuntimeBuilder::build_asynccalls
serially with no deadline above it. One such server hung the whole runtime
build rather than degrading its own connection. - A
tools/callwhose reply was lost on theapplication/jsonpath was
reported as a definite failure. Six exits between an accepted POST and a
parsed reply bypassed the indeterminacy classification the event-stream path
applied to all of them, so the same physical event got opposite answers
depending only on which framing the server chose — and the stalled-read case
was not merely reachable but unavoidable, sincestream_idle_timeoutalways
fires beforecall_tool_timeout. SinceMcpBridgedToolflattens the error
to itsDisplay, and onlyRequestIndeterminatesays "must not be retried
automatically", a model would retry a call that may have charged a card.
Both paths now classify in one place, exempting a JSON-RPC error, which is
the answer. - A server that forgot a session bricked itself permanently: the client
reportedSessionExpiredand stopped, no caller reconnected, and every tool
from that server stayed broken for the runtime's life. The specification
requires starting a new session, so the client now re-handshakes and re-sends
once. That is safe even for atools/call, because a 404 for an unknown
session is a refusal before dispatch. The replacement handshake runs through
a non-recovering path, so a recovery cannot start another recovery. - The negotiated protocol revision is now checked against the ones this client
implements instead of being echoed back unread. A consequence worth having:
the header carries one of our own&'staticconstants, so no
server-controlled bytes reach a request header on that path at all. - Smaller: the
tools/listpage cap rejected a list exactlymax_tool_pages
long (andmax_tool_pages: 1rejected every server); nothing bounded the
list those pages accumulate into, so a server could push gigabytes through
the walk and be stopped by the allocator rather than a limit (max_tools
now bounds it); a session id is echoed on every request and so is now marked
sensitive and held to the specification's visible-ASCII rule; a handshake
failing afterinitializeorphaned the server-side session, andshutdown
left a dead id in place; and a refused redirect is no longer treated as proof
a call did not run, since a 303 answering a POST means the server processed
it.
The fixture gained what it was missing — stalling, pagination, session expiry
and rotation, and per-method failures — and the suite went from 18 tests to
52. The two most important fixes were mutation-tested: reverting either makes
its test fail rather than pass quietly.
CI checks the code it was not checking
- Every CI job ran without
--all-features, so theopenai-oauthfeature was
never compiled, linted, or tested there — 831 lines of credential-store code,
which is precisely the kind that should not ship on the strength of a local
run. Clippy, the tests, and the MSRV check now all pass--all-features; the
MSRV floor still holds with them enabled. - Nothing built the documentation, so a broken intra-doc link was invisible to
the whole pipeline: it is neither a compile error nor a lint. Adocsjob now
builds the workspace withRUSTDOCFLAGS=-D warnings, which is what would have
caught the seven links repaired just above — including one that named a field
on the wrong type. - Nothing built the crate with its default features off either, though
responses-websocketis default-on specifically so a host that only streams
over HTTP+SSE can droptokio-tungstenitefrom its tree. That configuration
could have stopped compiling without failing anything; a job now checks it.
An MCP server can be reached over Streamable HTTP
- Streamable HTTP replaced HTTP+SSE in protocol revision 2025-03-26, and
current MCP servers are commonly streamable-only: they answer404on
/ssebecause they never implemented the older transport, and406on
/mcpbecause nothing in mentra sent anAcceptheader offering both reply
types. Such a server was reachable through neither existing transport, which
made an MCP integration impossible rather than degraded. McpStreamableHttpServerConfigandMcpStreamableHttpClientpost every
JSON-RPC message to the one configured endpoint and read each reply from that
same response, whether the server answers with a singleapplication/json
body or opens atext/event-streamin it.RuntimeBuildergains
with_mcp_streamable_http_serverandwith_mcp_streamable_http_servers, and
McpManagergainsconnect_streamable_http; the tools bridge exactly as the
other two transports' do.- The session
initializeassigns rides on every later request as
Mcp-Session-Id, andshutdownends it. A server is free to use no session
at all, in which case none is invented and no header is sent. - The transport buys a structural simplification worth naming: because a reply
arrives on the response to the request that asked for it, this client needs
no background reader task, no pending-request map, and no window in which a
response can arrive before its own request future resolves — all of which the
le...
mentra v0.10.0 — agentic-core hardening
mentra v0.10.0 / mentra-provider v0.4.0
Mentra 0.10 hardens the agentic core while preserving its architectural
contract: Mentra remains the sole owner of the model/tool loop, new host seams
stay generic, and default behavior changes only where explicitly documented
below.
This combined release covers the five hardening workstreams and the Proposed
coding-tools,
reasoning-preservation,
and host-orchestration
design records.
Highlights
Runtime hygiene and shell validation
- Remove the orphaned 5,924-line provider source tree. The live adapters remain
inmentra/src/provider.rsand continue to delegate tomentra-provider. - Add opt-in
ShellValidationMode::{Off, Warn, Enforce}classification for
builtin foreground and background shell execution. - Validation enriches authorization previews and reuses the existing
allow/prompt/deny vocabulary and hooks.Offremains the default. - Shell classification is defense-in-depth and permission UX, not a security
boundary; runtime roots, environment isolation, and process controls remain
the enforcement boundary.
Universal tool-result limits
- Apply one output boundary to successful and error results from builtin,
custom, and MCP tools, including parallel batches. - Defaults are 2,000 lines and 50 KiB per result. Truncation retains complete
lines and appends an actionable notice; under-limit output is byte-identical. - Oversized structured JSON is never sliced. When spill succeeds, it is written
whole and replaced by text pointing to the artifact; otherwise the text
notice explains why the full output was not saved. - Volatile stores suppress disk spill to preserve their no-durable-trace
contract. The existing shell stream-capture cap remains separate and applies
before this result boundary.
Model-conventional coding tools
- Add opt-in
read,ls,grep,glob,write, andedittools over the
existing transactionalWorkspaceEditor. FileToolProfile::{Batched, Split, Both}controls the advertised surface;
Batchedremains the default. Read operations use the parallel lane, while
write and edit use exclusive local mutation.- Grep gains file filters, literal and case-insensitive modes, context,
multiline regex, and a Unicode-safe 500-character cap per rendered physical
line. - Split
editvalidates all matches against the original content, rejects
ambiguity, overlaps, and no-ops, preserves BOM/CRLF, and supports an
NFKC/smart-punctuation fallback. - Diffs, patches, and
first_changed_lineremain localToolOutput::details;
providers receive only a short summary. - Recursive list, search, and glob traversal now reject descendant symlinks
that escape configured read roots. This is an intentional default-path
policy fix.
move and delete remain batched-only. Historical files.replace keeps its
exact-match semantics and does not gain fuzzy editing.
Thinking and reasoning continuity
- Add externally tagged
ContentBlock::Thinkingplus streaming start/delta
variants and persistence/replay support. - Capture and replay Anthropic signed/redacted thinking and OpenAI Responses
reasoning items, summaries, IDs, and encrypted content. - Emit reasoning text separately as
AgentEvent::ReasoningDeltaand
SessionEvent::AssistantReasoningDelta; signatures and ciphertext never
enter host text deltas. - Replay opaque reasoning only when registered provider, requested model, and
provenance format match exactly. Missing/empty metadata and cross-model or
cross-provider history downgrade to ordinary text instead of being dropped
or rejected. - Responses requests with reasoning enabled include
reasoning.encrypted_content; Azure-compatible late ciphertext is backfilled
from terminal output. - Thinking is persisted and may contain sensitive provider material. Local
compaction summarizer inputs explicitly exclude it.
Gemini thought/signature fidelity remains incomplete because signatures can
also attach to tool-use and text parts; that phase is deferred.
Steering and host orchestration
- Add agent-scoped in-memory steer and would-stop follow-up queues with
QueueMode::{OneAtATime, All}. Enqueueing never auto-starts an idle agent;
hosts callAgent::run_queuedexplicitly. - Steering wins over a user
RoundStrategyat a boundary without consuming
the strategy slot. Next-request context order is stable:
steering, then team inbox, then background notifications. - Drained steering is inflight-tracked and requeued on runner or finalization
errors. - Add typed
Runtime::task_boardandAgent::task_boardfaçades over the
existing access, transition, and DAG-validation path. - Add object-safe
TaskStore::mutate. SQLite, Volatile, and Hybrid stores
serialize mutations transactionally; custom stores retain a source-compatible
load/replace fallback. - Add
Agent::run_to_output<T>through an owner-scoped terminal tool and exact
tool_use_iddetail extraction. Provider-nativeresponse_formatremains
out of scope. - Add owned, generation-aware wait helpers for snapshots, idle completion, and
teammate replies. Seeexamples/host_orchestration.rsfor the end-to-end
host-scripted flow. - Make opaque team-protocol request IDs collision-resistant across
cross-second request interleavings.
Nous migration — read before upgrading
Upgrade both direct dependencies together:
[dependencies]
mentra = "0.10"
mentra-provider = "0.4"Nous imports provider-core types directly. Retaining mentra-provider 0.3
allows two provider-core versions into the graph and creates incompatible
types against Mentra's ContentBlock and tool-result surface.
Nous should also opt out of the generic result cap until its observation
protocol becomes truncation-aware:
use mentra::{Runtime, RuntimePolicy};
let policy = RuntimePolicy::default()
.with_max_tool_result_bytes(usize::MAX)
.with_max_tool_result_lines(usize::MAX)
.spill_full_tool_output(false);
let builder = Runtime::empty_builder().with_policy(policy);Why this is required today:
- Nous serializes each
ToolObservationas one physical JSON line. - Above 50 KiB, no complete line fits, so Mentra replaces the observation with
a truncation notice. - Nous cannot deserialize that notice and excludes the observation from its
reconstructed evidence. - Nous uses
VolatileRuntimeStore, which correctly suppresses disk artifacts,
so there is no spill file to recover. - Disabling spill alone is insufficient; both result limits must also be
raised. Add a regression using serialized output larger than 51,200 bytes.
Additional integration guidance:
- Treat Responses
tool_use_idvalues as opaque. Reasoning-bearing turns may
use localcall_id|function_item_idIDs; provider outputs still project the
raw call ID. Exact-equality pairing remains correct. - Existing wildcard
AgentEventandContentBlockmatches continue to
compile. HandleReasoningDeltaexplicitly only if live reasoning should be
surfaced. - Replay-only Responses mode benefits from preserved reasoning. A
gather-to-synthesis model switch safely downgrades incompatible opaque
reasoning to text. - Run a live Responses/xipe smoke after upgrading because reasoning-enabled
requests now ask providers for encrypted reasoning content.
Compatibility and source notes
- Old persisted transcripts, agent memory, and snapshots deserialize
unchanged. New optional fields are serde-defaulted and omitted when absent. - Under-limit tool results remain byte-identical. Oversized text intentionally
changes, and oversized structured results become textual truncation notices
that include an artifact pointer only when spill succeeds. - Exhaustive matchers must add cases for
ContentBlock,ContentBlockStart,
ContentBlockDelta,AgentEvent,SessionEvent, and
mentra_provider::responses::model::ResponsesInputItemreasoning variants. - Exhaustive
AgentSnapshotliterals must addrun_generation; patterns
should use... - Shell authorization preview JSON gains a
validationobject. InWarn
mode, the reusedAuthorizationDeniedhook is advisory; inspect its action
and outcome rather than treating the event name as proof execution stopped. - Existing custom
AgentStoreimplementations compile through the default
allows_disk_artifacts() == true; no-durable-trace stores should override it
to returnfalse. - Existing custom
TaskStoreimplementations compile through default
mutate, but that fallback is not atomic and should be overridden for
concurrent writers. - Default agents have empty steering queues, shell validation remains
Off,
and file tools remainBatched. - Public
time = "0.3"andurl = "2.5"requirements remain compatible with
downstream resolution. Resolver v3 and lockless Rust 1.85 CI enforce the
repository MSRV without exact public pins.
Operational caveats
TaskBoardreads are live, but façade mutations refresh an agent's cached
task snapshot only at the next normal refresh or run boundary.- The pre-existing full-board failed-run restore can overwrite a concurrent
successful task mutation that occurred after the snapshot was captured. - Agent memory, agent records, and run checkpoints do not share one atomic
store transaction. Steering/team/background input is requeued after late
errors, but earlier finalization writes may already have committed. wait_for_teammate_replyconsumes inbox delivery and must not race the agent
loop's inbox read. The host owns and must route the returned content.- An unsatisfied snapshot wait can remain pending while runt...
mentra v0.8.0
mentra v0.8.0
Mentra v0.8.0 adds two small, additive runtime controls for per-phase agent
tiering: changing reasoning options mid-session, and stopping a run gracefully
without discarding the work it gathered.
Highlights
Per-phase reasoning options
- Add
Agent::set_reasoning(Option<ReasoningOptions>)and the session wrapper
Session::set_reasoning(...), mirroringset_model: a stateful override threaded
into every subsequent model request and persisted with the agent record. - This makes a per-phase reasoning split expressible on a single agent — for
example, run the gather rounds at a low effort, then raise the effort (and,
together withset_model, switch to a stronger model) for a final synthesis turn
— without re-spawning the agent and losing the gathered context.
Graceful run stop
- Add
RunOptions::stop, a graceful-stop signal distinct fromcancellation. The
runner checks it at each round boundary, where the transcript is at a consistent
point. When it is tripped the run ends successfully, committing the gathered
transcript, instead of returningCancelledand rolling the run back. - Use it to stop a run once enough has been gathered while keeping the gathered
context available for a follow-up turn on the same agent.cancellationstill
aborts-and-rolls-back as before;stopis the keep-the-work variant.
Compatibility
- Both additions are additive.
RunOptionsgains one field (stop), defaulting to
None; constructions that use..RunOptions::default()are unaffected.
Crate Versions
mentra 0.8.0mentra-provider 0.3.0remains unchanged and does not need to be republished.
Verification
This release is expected to pass:
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace
v0.7.1
mentra v0.7.1
Mentra v0.7.1 is a compatibility patch for downstream workspaces that also
use newer sqlite bindings.
Compatibility
- Update
rusqlitefrom 0.32.1 to 0.39. - This aligns Mentra with the
libsqlite3-sys0.37 linkage family, avoiding
Cargolinks = "sqlite3"conflicts when Mentra is composed with crates that
already depend on currentrusqlite.
Repository Hygiene
- Ignore local
.graphagraph artifacts.
Crate Versions
mentra 0.7.1mentra-provider 0.3.0remains unchanged and does not need to be republished.
Verification
This release is expected to pass:
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace
v0.7.0
mentra v0.7.0 / mentra-provider v0.3.0
Mentra v0.7.0 is a provider and coding-agent release. It expands the runtime
with MCP support, safer shell execution primitives, provider-core embeddings,
custom compatible endpoints, and a fuller Responses API client for manual
coding-agent setups.
Highlights
MCP and Runtime Tooling
- Add a Model Context Protocol client, manager, protocol types, bridge, and test
coverage so MCP tools can participate in Mentra runtimes. - Add bash command validation for shell-tool execution.
- Add workspace-bounded runtime policies and sandbox detection helpers.
- Add
Session::set_model(...)for runtime model switching. - Emit usage-report events with token counts.
Provider-Core Improvements
- Add provider-core embedding contracts and a Responses embedding provider.
- Add custom provider-core endpoint registration so applications can target
compatible OpenAI, Responses, and Anthropic-style services. - Add Anthropic prompt caching controls through cache-control markers.
- Preserve and expose richer provider response metadata for runtime consumers.
Responses API and xipe
- Add
ResponsesStateMode::{ReplayOnly, Hybrid, Stateful}. - Track streamed response ids and send
previous_response_idwhen provider
state is enabled. - Retry hybrid HTTP/SSE requests without
previous_response_idwhen provider
state is unavailable or rejected. - Add first-class WebSocket transport for Responses streams.
- Send xipe-compatible WebSocket
response.createframes with request fields at
the top level. - Default Responses function tools to
strict: falseunless a tool explicitly
opts into strict mode. - Refresh
x-codex-turn-stateacross HTTP and WebSocket paths. - Add a manual coding-agent guide for Mentra + Responses + xipe.
Compatibility and Migration
- Publish
mentra-provider 0.3.0before publishingmentra 0.7.0. mentra 0.7.0depends onmentra-provider 0.3.0.- HTTP/SSE remains the default Responses transport.
ResponsesStateMode::Hybridis the recommended coding-agent default because
local transcript replay remains authoritative while provider-side state is
used opportunistically.- Existing built-in shell and files tool schemas stay flexible because
Responses function tools serialize as non-strict by default.
Verification
This release is expected to pass:
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace
Live xipe smoke testing also covered gpt-5.4-mini over HTTP/SSE and
WebSocket Responses transports.
v0.6.0
What's New in Mentra v0.6.0
Permission Scope Hierarchy
PermissionRuleStorenow supports cross-session rules via consumer-suppliedproject_id- Session, Project, and Global scopes with hierarchical lookup (most specific wins)
- Automatic SQLite schema migration for existing databases
Compaction Hardening
- Auto-compaction retries up to 3 times on transient errors, then degrades gracefully (session continues with micro-compaction instead of dying)
- Configurable transcript cleanup (
max_persisted_transcripts) prunes old JSONL files - Mock test coverage for remote compaction paths (PreferRemote fallback)
Long-Session Stress Testing
SessionGeneratortest utility for building multi-turn scripted sessions- 50-turn CI integration tests with compaction chains
- Resume-after-compaction tests
- Criterion benchmarks for 500-turn sessions, memory scaling, and resume performance
Pattern-Based Approval Rules
RuleStore::check()now matches glob patterns against serialized tool input JSON- Pattern rules take precedence over no-pattern rules (specific deny overrides general allow)
- Uses
glob-matchcrate for*/?pattern syntax
Pre-Execution Hook System
- New
PreExecutionHooktrait withAllow/Denydecisions (separate from observe-onlyRuntimeHook) PreExecutionHookscollection with first-deny-wins semanticsRuntimeBuilder::with_pre_hook()for registration- Integrated into both exclusive and parallel tool execution paths
ToolExecutionBlockedevent for observability
Public Team API
Session::spawn_subagent(name, prompt)for programmatic subagent creation (async, non-blocking)Session::list_teammates()andSession::active_subagents()for team state observationSubagentHandle,SpawnedAgentSummary,SpawnedAgentStatuspublicly exported
Other
- 333 tests (up from ~280 in v0.5.0)
- Criterion benchmarks behind
test-utilsfeature flag
Breaking Changes
PermissionRuleStore::save_rules()andload_rules()now requireproject_id: Option<&str>parameterRuleStore::check()now requiresinput_json: Option<&str>parameter
v0.5.0
mentra v0.5.0 / mentra-provider v0.2.0
Mentra v0.5.0 is a tooling-architecture release. The headline change is a
cleaner boundary between provider-facing contracts and runtime-facing
orchestration, with the provider surface now published as the new
mentra-provider crate.
This release also adds a full session lifecycle API, persisted permission
resolution, richer tool progress events, more provider/runtime coverage, and a
large round of test and CI hardening.
Highlights
New mentra-provider crate
- Extract provider-facing request, response, model, stream, auth, and tool
contracts into the newmentra-providercrate. - Keep provider serialization concerns separate from Mentra runtime scheduling
and approval semantics. - Add Responses transport primitives, including websocket support, HTTP fallback
controls, metadata event preservation, hosted action contracts, replay, and
remote compaction support.
Tooling architecture refactor
- Split provider-facing and runtime-facing tool contracts into explicit layers.
- Introduce dedicated tool orchestration with execution-lane scheduling.
- Refactor builtin, files, and intrinsic tooling into thinner facades with
focused internal modules. - Emit richer
ToolProgressevents for shell execution output and file
operations.
Session and permission APIs
- Add the
Sessionlifecycle surface, session event mapping, hooks, and typed
session flow support. - Persist permission rules to SQLite so resumed sessions can keep their approval
state. - Support live permission resolution during active sessions.
- Preserve live agent events during turns when sessions are resumed.
Runtime and provider improvements
- Add transcript compaction and memory summarization plumbing, plus remote
compaction support in the provider layer. - Add Ollama and LM Studio support through the OpenAI-compatible Responses API.
- Improve Windows shell execution behavior and strengthen cross-platform CI
coverage. - Forward session headers on provider requests where needed.
Verification and quality
- Expand integration coverage for session lifecycle, runtime tools, compaction,
resume flows, error recovery, and contract conformance. - Tighten CI and test behavior across Unix and Windows environments.
Compatibility and migration
ToolDefinition,ToolExecutor,ToolSpec, andExecutableToolremain
available in this release.ToolSpec::builder(...)remains the supported convenience API for custom
tools.- Implement read-only tools with
ToolExecutor::execute(...). - Implement mutating or agent-state-changing tools with
ToolExecutor::execute_mut(...). - Provider-visible tool metadata now lives in
mentra-provider, while runtime
scheduling and approval metadata stay inmentra.
Publishing order
Publish mentra-provider 0.2.0 before publishing mentra 0.5.0.
v0.3.0
v0.3.0 focuses on safer tool execution and better runtime resilience for agentic workflows.
Full Changelog: v0.2.0...v0.3.0
Highlights
- Added a generic tool-authorization seam to the runtime
- Added pre-execution tool authorization with structured input previews
- Simplified runtime command-review behavior by removing shell review heuristics
- Improved malformed tool-call handling so invalid tool JSON can recover instead of aborting the whole run
- Expanded provider-neutral token usage reporting across built-in provider streams and runtime hooks
What’s New
Tool authorization
Mentra can now run a caller-provided authorization pass before a tool executes. This gives applications a clean integration point for:
- LLM-based security review
- human approval flows
- custom policy engines
- fail-closed blocking for risky tool calls
Authorization requests include structured previews so callers can make decisions on normalized tool input instead of raw prompt text.
Better malformed tool-call recovery
A malformed tool-call JSON payload no longer has to kill the entire run. Mentra now treats invalid tool input more gracefully and feeds retry guidance back into the conversation so the model can correct itself on the next round.
This makes tool-using agents more robust in quote-heavy or long-context flows where malformed function-call JSON occasionally happens.
Token usage reporting
Built-in provider streams now populate a shared token-usage model, and runtime hooks report model response usage more consistently across OpenAI, Anthropic, and Gemini integrations.
Behavioral changes
- Tool authorization types now live under
mentra::tool - Runtime command-review internals were simplified by removing shell review heuristics
- If you were relying on older
runtimere-exports for authorization-related types, you may need to update imports
Upgrade notes
If you are adopting tool authorization, check the README examples for the current import path and builder usage.
Typical usage now looks like:
- define a
ToolAuthorizer - return
allow,prompt, ordeny - install it with
Runtime::builder().with_tool_authorizer(...)
If you previously worked around malformed tool-call JSON failures at the app layer, you may be able to remove some of that logic in 0.3.0.