QueryMT Agent - API Reference
This document provides a reference for the QueryMT Agent public API.
Module Structure
Prelude
The prelude module re-exports the most commonly used types:
Agent Creation
Single Agent
Use Mesh::hybrid() when you want one process-shared runtime that supports both LAN discovery and later iroh invite joins.
Multi-Agent (Quorum)
From Config
Agent Types
Agent
The main agent runtime, supporting both single and multi-agent modes.
Methods
| Method | Description |
|---|---|
chat(&self, message: &str) -> Result<String> |
Send a message and get response |
new_session(&self) -> Result<AgentSession> |
Create a new session |
list_sessions(&self) -> Result<Vec<SessionInfo>> |
List active sessions |
mesh(&self) -> Option<AgentMesh> |
Access mesh APIs when the agent was built with mesh support |
subscribe_events(&self) -> Receiver<EventEnvelope> |
Subscribe to events |
shutdown(&self) -> Result<()> |
Gracefully shutdown |
AgentMesh
Mesh-aware facade returned by agent.mesh().
Methods
| Method | Description |
|---|---|
join(&self, invite: impl AsRef<str>) -> Result<MeshJoinOutcome> |
Join an iroh mesh scope on the shared runtime |
ensure_published(&self) -> Result<()> |
Publish local mesh actors for this agent |
runtime(&self) -> &MeshRuntimeHandle |
Access the underlying shared runtime handle |
AgentSession
Per-session interface for agent interaction.
Methods
| Method | Description |
|---|---|
chat(&self, message: &str) -> Result<String> |
Send message in this session |
cancel(&self) -> Result<()> |
Cancel current operation |
set_mode(&self, mode: AgentMode) -> Result<()> |
Change agent mode |
set_allowed_tools(&self, tools: &[String]) -> Result<()> |
Set allowed tools |
set_denied_tools(&self, tools: &[String]) -> Result<()> |
Set denied tools |
get_history(&self) -> Result<Vec<AgentMessage>> |
Get conversation history |
fork(&self, instructions: &str) -> Result<AgentSession> |
Fork to new session |
Agent Modes
Mode Switching
Callbacks
MessageCallback
Called when a message is sent or received.
ToolCallCallback
Called before a tool is executed.
ToolCompleteCallback
Called after a tool completes.
DelegationCallback
Called during delegation operations.
ErrorCallback
Called when an error occurs.
Events
EventEnvelope
AgentEventKind
The concrete event enum evolves over time; consult crates/agent/src/events.rs for the canonical Rust definition. Common event families include session lifecycle, prompts/messages, tool execution, permissions, compaction, delegation, and hook diagnostics.
Hook-related diagnostics are surfaced as:
hook_notice is emitted when a hook exits successfully but returns invalid output that QueryMT ignores for control-flow purposes.
Cost accounting
Cost is a supported token-cost estimate computed from recorded provider usage and the pricing bound when each request was sent. It is not a provider invoice. Four scopes are used, and every figure belongs to exactly one of them:
| Scope | Meaning | Where it appears |
|---|---|---|
| attempt | One physical provider request. A retry is a new attempt. | llm_attempt_started / llm_attempt_settled (the durable ledger) |
| operation | One logical model request, i.e. all of its attempts. | llm_request_end.cost_usd and llm_request_end.accounting |
| cycle | Everything attributed to one execution cycle (one prompt run). A new cycle starts at zero. | AgentStats cost fields (a read-only view) |
| session | Everything recorded for the session, across cycles and restarts. | llm_request_end.cumulative_cost_usd |
llm_request_end is derived presentation. It is never an additional ledger entry, and new accounting is recorded only through the attempt events.
cost_usdis the complete supported cost of the whole operation, retries included, and includes cache read and write charges. It isnullunless that total is complete.cumulative_cost_usdis the session total, with the samenullrule. A session total is complete only when nothing in it is unresolved or incomplete, so a single interrupted attempt clears it. An all-excluded session (for example a subscription provider) has no dollar amount instead of a known zero.accounting.attempt_idsandoperation_idmatch the durable attempt records, so consumers can deduplicate.known_subtotal_usdandreasonsexplain anullcost. Events written before accounting existed omitaccounting.- An execution that ends before a normal
llm_request_end(cancellation, error) still has its attempts recorded. Its charges and uncertainty are in the attempt events and the session total, but no request-end event is emitted for it. - Retry attempts are valued separately. A rejected attempt that reports usage is charged; a provider-confirmed non-billable rejection adds nothing; an unconfirmed transport failure stays uncertain rather than zero.
Auxiliary generation
Besides the main response, two components make paid provider requests. Both are recorded in the same ledger, with their own purpose, and neither changes the main conversation's context size or step counters:
| Purpose | Dispatched by | Charged to |
|---|---|---|
main_response |
the execution loop | the executing cycle |
compaction |
AI context compaction | the cycle that triggered it (a dedicated maintenance-… cycle when compaction runs outside a prompt) |
delegation_summary |
the delegation planning summary | the parent cycle that requested the delegation |
Compaction lowers the effective context while increasing spend. A summary refused or rejected by validation (empty, truncated, or with tool calls) still incurs and records its usage, and each retry is a separate attempt.
Every dispatch site is either recorded or explicitly classified. The AgentRunner::chat / Agent::chat convenience API runs an ordinary prompt cycle and so reaches a provider only through the recorded main loop. SessionHandle::submit_request and SessionHandle::chat require a ledger argument and have no unrecorded variant. A test (accounting::dispatch_coverage_tests) fails if a new provider call appears outside this list. A node that merely hosts a provider for a remote peer does not record the attempt: the requesting node's session does, because the host has no session to charge.
Accounting metadata (ACP)
Clients receive the reducer's state as one versioned replacement DTO, AccountingSnapshot (generated TypeScript: target/generated/types.ts, produced with PATH=/Users/wiking/.cargo/bin:$PATH ./scripts/generate-types.sh). The same payload is carried three ways:
| Carrier | When | Where |
|---|---|---|
usage_update |
a reliable main-context measurement and the active model's limit are known | _meta.querymt.accounting |
session_info_update |
otherwise (unknown limit, or a model switch invalidated the last measurement) | _meta.querymt.accounting; no title/updatedAt, no fabricated used/size |
SessionLoadSnapshot |
session/load |
the required accounting field, reduced from the same audit events as cursor, present even without historical replay |
Delivery does not depend on negotiated notice support or on the context size. Attempt starts are not published (they would flash an incomplete total during every request); each settlement that changes state is, and an identical redelivery publishes nothing.
A cost that turns incomplete keeps its known subtotal and replaces the total with an explicit null:
Semantics:
- Replacement. A present payload replaces the previous accounting state atomically.
completeTotalUsdandcycleare always serialized (explicitnull), never omitted. A message without the payload does not touch accounting. Omission of standard ACPcostalone is not a clearing signal. - Standard
cost. Sent onusage_updateonly from the session's complete metered estimate. It is omitted when the total is partial, unresolved, all-excluded or based on legacy history, andusage_update'scostis never taken fromllm_request_end.cumulative_cost_usd. - Scopes.
sessionis lifetime API spend.cycleis the cycle of the most recent main-response attempt, ornullwhen there is none; a delayed compaction or summary settling for an older cycle never selects that cycle as active.billingisempty,metered,excluded(never a zero-dollar invoice) ormixed(amounts cover metered attempts only). - Budget view.
cycle.budgetis the valuationmax_price_usdenforces: manual rates when configured, otherwise the recorded API valuation. It is kept apart from API spend;reasonslists settled gaps only (in-flight attempts are not a reason) andbestEffortis true when the cap is enforced against a known subtotal. - Token telemetry is separate.
_meta.querymt.usagev1 (latestRequest,sessionTotals,partial) keeps its shape and its main-request token scope. Retry and auxiliary attempts do not enter it, so its totals are not the monetary ledger's tokens. - Ordering. Live and replayed delivery reduce the same records, so they agree. Snapshot and captured-live application use the existing local/remote cursors; older state never overwrites newer accounting, and a duplicate is a no-op.
- Export. ATIF
final_metrics.total_cost_usdis the reducer's complete session total or absent.final_metrics.extracarries the sameaccountingsnapshot plus anattemptslist covering main, auxiliary, failed and unresolved attempts. A step'smetrics.extra.accountinggives an incomplete operation's known subtotal and reasons. Auxiliary attempts have no step, and anllm_request_endwithoutaccounting(legacy history) exports no dollar cost.
Required client behavior (querymt-desktop follow-up)
This repository defines the payload only. The desktop client must be updated together with the backend:
- Apply the payload atomically and treat a present
nullcompleteTotalUsdas "cleared". Do not writeupdate.cost ?? previous. mergeMissingSessionUsagemust not refill an intentionally cleared cost from an older candidate. Merge precedence follows the snapshot/live cursors.- Hydrate from
SessionLoadSnapshot.accounting. Stop deriving money fromllm_request_end.cumulative_cost_usd; token-history telemetry may stay as is. - Read the same DTO from
usage_updateorsession_info_update, and do not refresh the session catalog for an accounting-onlysession_info_update(it changes no summary field). - Label figures as "Estimated API cost" (complete), "Known API subtotal - incomplete" (with reasons) and "Subscription usage excluded"; show the manual-rate cycle budget separately.
Breaking changes and deployment
Usagegains optionalcache_write_tiers;ModelPricinggains cache and one-hour write rates and applicability metadata;LlmRequestEndgainsaccounting; the eventsllm_attempt_started/llm_attempt_settledare new;SessionLoadSnapshotgainsaccounting;AgentStatscosts are views of recorded components and the aggregate-token repricing helpers are removed. There are no legacy adapters.- Upgrade the backend, providers/plugins, remote peers, bindings and clients together. Mixed-version accounting is not supported.
- Existing sessions keep their history. Local generation recorded before accounting has no basis and is reported as
unaccountedGenerations, so such a session never claims a complete total, and no historical rates are applied. - Rollback needs matching binaries and a database copy taken before the upgrade. Do not run an older event decoder against a journal containing the new events, and do not delete accounting events to make a rollback succeed.
Delegation
Delegation
DelegationStatus
VerificationSpec
Middleware
MiddlewareDriver
CompositeDriver
Tools
ToolRegistry
Built-in Tools
| Tool | Description |
|---|---|
read_tool |
Read file contents |
edit |
Edit file with patch |
write_file |
Write/overwrite file |
delete_file |
Delete file |
shell |
Execute shell command |
glob |
File pattern matching |
search_text |
Text search in files |
ls |
List directory contents |
create_task |
Create task |
todowrite |
Update todo list |
todoread |
Read todo list |
question |
Ask user question |
web_fetch |
Fetch web content |
Configuration Types
AgentConfig
ToolConfig
ExecutionPolicy
Error Handling
AgentError
ACP (Agent Client Protocol)
Transport
RPC Messages
Remote/Mesh API
Mesh Configuration
Remote Session
Examples
See examples/ directory for complete usage examples:
qmtcode.rs- Full-featured coder agentacp_agent.rs- ACP stdio serverauto_delegation_example.rs- Multi-agent delegationfrom_config.rs- Configuration-based agentmorning_brief.rs- Daily summary agentreplay_session.rs- Session replay
Version Compatibility
| QueryMT Agent | QueryMaTe | Rust Edition |
|---|---|---|
| 0.2.x | 0.2.x | 2021 |
| 0.1.x | 0.1.x | 2021 |
Breaking Changes
v0.2.0
AgentHandletrait introduced for unified local/remote interface- Delegation uses
AgentHandle::create_delegation_session() SessionActornow uses kameo actor model- Event system uses
EventFanoutinstead of direct subscriptions
v0.1.0
- Initial release with single-agent support