package murmur:tool@0.1.0;
interface run {
enum status {
passed,
failed,
error,
}
record tool-input {
data: option<string>,
log-path: option<string>,
}
record tool-result {
status: status,
summary: option<string>,
data: option<string>,
data-path: option<string>,
truncated: bool,
/// Free-form key/value channel from a driver or tool back to the host.
///
/// Reserved key `"continuation_id"`: an inference driver that holds
/// conversation state provider-side (so the host need not resend the full
/// transcript on every Turn) opts in by returning this key with a
/// non-empty value on any Turn's response. The host persists it for the
/// current session loop and, on the next Turn under the same context,
/// transmits only the messages appended since the driver last acknowledged
/// state, plus this id (as the request-side `continuation_id` field),
/// instead of the full `messages` array. Returning the key with an
/// empty-string value, or omitting it, means "not continuing": the host
/// drops any held id and resends in full. If the list carries more than
/// one `continuation_id` tuple, the host uses the first in list order.
/// A driver that never sets this key (every driver shipped today) sees no
/// behavior change.
///
/// Reserved key `"state_effect"`: how this call affected the resource it
/// addressed, declared by the tool itself so host observability (e.g.
/// `mur trace` redundant-call detection) can reason about it without
/// knowing which tool this is. Recognized values: `"read"` (the call only
/// observed state — a repeat against the same unchanged resource is
/// redundant) and `"mutate"` (the call changed state — it invalidates any
/// earlier read of that resource). Any other value, or omitting the key,
/// means "unknown": the host treats the call conservatively (like a mutate
/// for invalidation purposes) and never credits it as a redundant read. A
/// tool that declares nothing is never misreported; it simply gets no
/// redundant-read detection of its own. The key is per-call, so one tool
/// with several operations declares the effect appropriate to each.
///
/// Reserved key `"resource_id"`: which resource this call addressed,
/// declared by the tool itself. The value is an opaque, tool-defined
/// string that the host records verbatim and never parses — two calls
/// address the same resource exactly when their `resource_id` values are
/// byte-equal. Declaring it is how a tool tells host observability (e.g.
/// `mur trace` redundant-call detection) *what* a call addressed, the
/// companion to `state_effect`'s *how it was affected*; the two are only
/// useful together. Omitting the key, or returning it with an
/// empty-string value, means "undeclared": the host falls back to
/// guessing the resource from a path-like field in the call's input,
/// which is all it could ever do before this key existed. A tool whose
/// resource is not a filesystem path (a symbol, a URI, a query) should
/// declare this key — it is the only way such a tool gets correct
/// detection, since no input-guessing heuristic can recognize its
/// addressing scheme. Scoping the value (e.g. `"sym:Foo::bar"`) keeps it
/// from colliding with an unrelated resource that happens to share a
/// name. If the list carries more than one `resource_id` tuple, the host
/// uses the first in list order. A tool that never sets this key (every
/// tool shipped today) sees no behavior change.
///
/// Reserved key `"transient"`: whether an inference driver's failed call
/// may succeed if the host makes it again. `"true"` marks the failure
/// transient: a stream that broke after the provider answered `200`, or a
/// provider error event mid-stream. The host then sends the same payload
/// again after a backoff, within the capsule's `inference.retry` bounds.
/// `"false"` vetoes a retry of a status the host would otherwise retry,
/// such as a `429` the provider reports as a permanent quota failure.
/// Any other value, or omitting the key, leaves the decision to what the
/// host's credential gateway saw: a `408`, `429` or retryable `5xx`, or a
/// connection that broke before a response arrived. Read only on a
/// failed inference call; if the list carries more than one `transient`
/// tuple, the host uses the first in list order.
metadata: list<tuple<string, string>>,
}
run: func(input: tool-input) -> tool-result;
}