Skip to main content

RunMeta

Struct RunMeta 

Source
pub struct RunMeta {
Show 35 fields pub run_id: String, pub agent_name: String, pub agent_path: String, pub task: String, pub model: Option<String>, pub pid: u32, pub status: RunStatus, pub current_stage: String, pub stage_index: usize, pub num_stages: usize, pub iteration: usize, pub prompt_tokens: usize, pub completion_tokens: usize, pub cached_tokens: usize, pub cache_write_tokens: usize, pub tool_calls: usize, pub workdir: String, pub started_at: i64, pub updated_at: i64, pub last_progress_at: Option<i64>, pub error: Option<String>, pub title: Option<String>, pub metadata: HashMap<String, String>, pub callback_url: Option<String>, pub callback_secret: Option<String>, pub parent_run_id: Option<String>, pub children: Vec<String>, pub depth: usize, pub max_child_depth: usize, pub flags: RunFlags, pub yolo: bool, pub read_paths: Option<ReadPathGrantCounts>, pub final_output: Option<FinalOutputDescriptor>, pub waiting_on: Option<WaitReason>, pub output_request: Option<OutputSpec>,
}
Expand description

Metadata for a single background agent run.

Fields§

§run_id: String

Identifies the run everywhere, and names its directory under ~/.leviath/runs/. Assigned at spawn and never reused.

§agent_name: String

The blueprint’s [agent] name, not the file it was loaded from. Two runs of the same agent from different paths share this.

§agent_path: String

Absolute path to the agent manifest directory

§task: String

The task text the run was started with, verbatim.

§model: Option<String>

The provider/model actually resolved for the entry stage, or None before resolution. Later stages may use a different one; this is not rewritten to follow them.

§pid: u32

Always 0. There is no worker process per run: the daemon hosts every run as an entity in one shared world, so no run has a pid of its own.

Kept because it is written into every meta.json there has ever been, and served from GET /api/agents. Do not key liveness on it. pid == 0 is true of a run that is working, a run that has finished, and a run nothing is driving, so a sweeper that reverts on it reverts everything. Ask the daemon (lev ps) whether it is still hosting the run, and read status and last_progress_at off disk for what became of it.

§status: RunStatus

Where the run stands. The durable counterpart to the ECS world’s live AgentStatus, and the one that survives a daemon restart.

§current_stage: String

Name of the stage the run is in, matching a key under [stages].

§stage_index: usize

Zero-based position of current_stage in the blueprint’s stage list. Not a progress measure: stages can loop and revisit.

§num_stages: usize

How many stages the blueprint declares, so a reader can render stage_index as “3 of 7” without loading the manifest.

§iteration: usize

Inference turns taken in the current stage, reset on entering a new one. Compared against the stage’s max_iterations.

§prompt_tokens: usize

Cumulative input tokens billed across every inference this run has made, including retries.

§completion_tokens: usize

Cumulative output tokens billed across every inference this run has made.

§cached_tokens: usize

Cumulative tokens read from provider cache.

§cache_write_tokens: usize

Cumulative tokens written to provider cache.

§tool_calls: usize

Total number of tool calls made across all iterations.

§workdir: String

Absolute path to the working directory for tool execution

§started_at: i64

Unix timestamp (seconds)

§updated_at: i64

Unix timestamp (seconds)

§last_progress_at: Option<i64>

Unix seconds when this run last actually moved: a new iteration, a new stage, or a change of status. None before the first snapshot lands, and on runs written by a daemon older than this field.

Distinct from updated_at, which also advances on the 30-second persistence heartbeat and so stays fresh on a run that is wedged. A fresh updated_at is evidence the daemon is alive, and no evidence at all about the run. Anything that ages a run must read this instead. Note that a daemon restart resets it: a reloaded run really is re-driven from its saved context, so it really has just moved.

§error: Option<String>

What went wrong, set alongside RunStatus::Error. None on every other status.

§title: Option<String>

Short human-readable title generated from the task prompt (None until generated).

§metadata: HashMap<String, String>

Custom key-value pairs from the spawn request (API metadata).

§callback_url: Option<String>

Webhook URL to POST on agent completion/error.

§callback_secret: Option<String>

Optional shared secret used to HMAC-SHA256 sign the webhook body (X-Leviath-Signature header) so the receiver can verify authenticity.

Persisted, because the daemon must still be able to sign a webhook for a run it reloaded after a restart. Never serve it - strip it with RunMeta::redacted before any of this struct leaves the process. See that method for what went wrong.

§parent_run_id: Option<String>

Links sub-agent runs to their parent run.

§children: Vec<String>

Run-ids of this agent’s direct sub-agents (sub-agent-tool spawns and fan-out workers). Persisted so the daemon can rebuild the exact parent→children tree on restart rather than reload children as orphans.

§depth: usize

This agent’s depth in the sub-agent tree (0 for a top-level run). Persisted so a reloaded child enforces its remaining spawn-depth budget.

§max_child_depth: usize

The sub-agent depth cap this agent imposes on its own children (0 when it has none). Restores SubAgentChildren::max_child_depth.

§flags: RunFlags

Why this run may have produced nothing useful - see RunFlags.

§yolo: bool

Whether the run was launched unattended (--yolo), so a daemon restart resumes it the way it was started.

This used to be dropped on reload, on the reasoning that forgetting a launch override can only prompt more, never less. In practice it meant a restart silently converted an unattended run into one parked on a prompt nobody was watching for - the operator’s own consent, given at launch, discarded by an implementation detail they never saw. Runs written before this field existed default to attended, so nothing is escalated retroactively.

§read_paths: Option<ReadPathGrantCounts>

How much of the blueprint’s [read_paths] the config granted, as resolved at spawn. None for a blueprint that declared none, and for runs written before this field existed.

§final_output: Option<FinalOutputDescriptor>

What the agent handed back, if it submitted anything: everything about the answer except the bytes.

This is the run’s answer, as distinct from error (why it failed) and from the stage logs (what it did along the way). The content itself is in a sidecar file beside this one, because this file is parsed for every run on every listing and must stay small no matter how long an answer is.

§waiting_on: Option<WaitReason>

Why this run is parked, when it is. None on every other status, and on a run written before this field existed. Same vocabulary the live listing reports, so lev ps and a client reading this file describe a run the same way.

Additive on purpose: default means a meta.json from an older build still loads, and skip_serializing_if means a run that is not parked writes exactly the file it wrote before, so an older build reading a newer run sees nothing new either.

§output_request: Option<OutputSpec>

The output shape this run was launched asking for, when the caller overrode the blueprint’s.

Persisted for the same reason yolo is: a daemon restart rebuilds the run’s spawn arguments from this file, and dropping the request would silently revert the run to the blueprint’s shape partway through. The caller asked once and should not have to ask again.

Implementations§

Source§

impl RunMeta

Source

pub fn redacted(&self) -> RunMeta

This run’s metadata with the webhook signing secret removed, for anything that leaves the process.

GET /api/agents, /api/agents/{id} and /api/agents/{id}/children all serialized RunMeta whole, so any holder of the API token could read every run’s callback_secret - the key that authenticates Leviath’s webhooks to their receivers. Mirrors the RedactedConfig pattern the /api/config handler already uses correctly.

Returns an owned copy rather than mutating in place so a caller cannot accidentally redact the record the daemon still needs for signing.

Source

pub fn new( run_id: String, agent_name: String, agent_path: String, task: String, model: Option<String>, workdir: String, num_stages: usize, ) -> RunMeta

A newly accepted run: RunStatus::Starting, both timestamps now, every counter at zero and every optional field unset.

Only the seven values a caller genuinely knows at spawn are parameters. Everything else is filled in by the daemon as the run proceeds, so taking them here would invite a caller to invent a stage or a token count.

Source

pub fn touch(&mut self)

Stamp updated_at with the current time.

Deliberately does not touch last_progress_at: the 30-second persistence heartbeat calls this, and a run that is wedged must not look like one that just moved. See RunMeta::last_progress_at.

Trait Implementations§

Source§

impl Clone for RunMeta

Source§

fn clone(&self) -> RunMeta

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RunMeta

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for RunMeta

Source§

fn deserialize<__D>( __deserializer: __D, ) -> Result<RunMeta, <__D as Deserializer<'de>>::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for RunMeta

Source§

fn eq(&self, other: &RunMeta) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for RunMeta

Source§

fn serialize<__S>( &self, __serializer: __S, ) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for RunMeta

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of this value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more