Skip to main content

Api

Trait Api 

Source
pub trait Api:
    Send
    + Sync
    + 'static {
Show 19 methods // Required methods fn list_agents( &self, ) -> impl Future<Output = Result<AgentList, Problem>> + Send; fn get_costs( &self, query: GetCostsQuery, ) -> impl Future<Output = Result<CostReport, Problem>> + Send; fn list_pending( &self, ) -> impl Future<Output = Result<PendingList, Problem>> + Send; fn send_flight( &self, body: SendFlightRequest, ) -> impl Future<Output = Result<FlightAccepted, Problem>> + Send; fn cancel_flight( &self, path: CancelFlightPath, ) -> impl Future<Output = Result<PendingList, Problem>> + Send; fn get_graph( &self, query: GetGraphQuery, ) -> impl Future<Output = Result<RouteMap, Problem>> + Send; fn engage_ground_stop( &self, ) -> impl Future<Output = Result<GroundStop, Problem>> + Send; fn release_ground_stop( &self, ) -> impl Future<Output = Result<GroundStop, Problem>> + Send; fn get_health(&self) -> impl Future<Output = Result<Health, Problem>> + Send; fn list_help( &self, query: ListHelpQuery, ) -> impl Future<Output = Result<HelpList, Problem>> + Send; fn resolve_help( &self, body: ResolveHelpRequest, ) -> impl Future<Output = Result<HelpResolved, Problem>> + Send; fn list_itineraries( &self, query: ListItinerariesQuery, ) -> impl Future<Output = Result<ItineraryList, Problem>> + Send; fn list_learnings( &self, query: ListLearningsQuery, ) -> impl Future<Output = Result<LearningList, Problem>> + Send; fn judge_learning( &self, path: JudgeLearningPath, body: JudgeLearningRequest, ) -> impl Future<Output = Result<Learning, Problem>> + Send; fn list_pipelines( &self, ) -> impl Future<Output = Result<PipelineList, Problem>> + Send; fn list_runs( &self, query: ListRunsQuery, ) -> impl Future<Output = Result<RunList, Problem>> + Send; fn get_run( &self, path: GetRunPath, ) -> impl Future<Output = Result<Run, Problem>> + Send; fn get_report( &self, path: GetReportPath, ) -> impl Future<Output = Result<Report, Problem>> + Send; fn stream_run( &self, path: StreamRunPath, ) -> impl Future<Output = Result<EventStream, Problem>> + Send;
}
Expand description

Everything the Tower must implement to serve this API.

One method per operationId. Adding an operation to api/openapi.yaml adds a method here, so an unimplemented endpoint is a compile error rather than a 404 discovered in production.

Required Methods§

Source

fn list_agents(&self) -> impl Future<Output = Result<AgentList, Problem>> + Send

Every configured agent and the route map between them.

This is the UI’s graph view, and it is also how a human answers “what can talk to what” without reading the TOML.

GET /agents

Source

fn get_costs( &self, query: GetCostsQuery, ) -> impl Future<Output = Result<CostReport, Problem>> + Send

What the factory has spent, and how much of that is measured.

A single Fuel figure says whether a chain may continue. This says where the money went — per agent, per model — and, critically, how much of the total the runners actually reported rather than Layover inferring it from a rate card.

Treat confidence as part of the number. A total that is mostly measured is still not measured, so any estimated or unreported run downgrades the whole figure.

GET /costs

Source

fn list_pending( &self, ) -> impl Future<Output = Result<PendingList, Problem>> + Send

Flights waiting for something to dispatch them.

Work that has been asked for and not yet started. Until the supervisor exists this is everything anybody has triggered; afterwards it is the backlog.

GET /flights

Source

fn send_flight( &self, body: SendFlightRequest, ) -> impl Future<Output = Result<FlightAccepted, Problem>> + Send

Start work by sending the first flight of a new itinerary.

Give either a pipeline or a to. A pipeline is the normal way in: it names the entry agent and declares which flags may be set. A bare to sends to an agent marked entry = true and accepts no flags.

The flight is queued, not run. Dispatching it needs the supervisor, which is not part of this release, so 202 means the work is booked and durable — it will start when there is something to start it. GET /flights shows what is waiting.

POST /flights

Source

fn cancel_flight( &self, path: CancelFlightPath, ) -> impl Future<Output = Result<PendingList, Problem>> + Send

Take a queued flight back off the queue.

Only work that has not started can be cancelled. A run that is already going is stopped with a Ground Stop, which is a different decision with a different blast radius — one flight versus the whole factory — and conflating them would make the smaller action feel as dangerous as the larger one.

DELETE /flights/{flight_id}

Source

fn get_graph( &self, query: GetGraphQuery, ) -> impl Future<Output = Result<RouteMap, Problem>> + Send

The route map as a diagram, with what is happening drawn on it.

Mermaid source, generated from the configuration as it is on disk right now. Edit layover.toml and reload; the diagram changes with it, because nothing here is baked at build time.

Agents currently running, waiting at a barrier, or freshly failed are coloured. An edge into a joined agent from a sender the barrier does not name is drawn as bypassing it, which is what actually happens.

GET /graph

Source

fn engage_ground_stop( &self, ) -> impl Future<Output = Result<GroundStop, Problem>> + Send

Halt everything.

Ground Stop is a file on disk rather than in-memory state, so it survives a Tower crash and can be set by hand when nothing else is responding.

POST /ground-stop

Source

fn release_ground_stop( &self, ) -> impl Future<Output = Result<GroundStop, Problem>> + Send

Resume.

DELETE /ground-stop

Source

fn get_health(&self) -> impl Future<Output = Result<Health, Problem>> + Send

Liveness, version and whether a Ground Stop is engaged.

GET /health

Source

fn list_help( &self, query: ListHelpQuery, ) -> impl Future<Output = Result<HelpList, Problem>> + Send

What agents are stuck on.

A lights-out factory’s worst failure is not a crash — a crash is loud. It is an agent that quietly cannot do what it was asked, produces something plausible anyway, and passes it downstream. This is the channel that stops that being invisible.

Measured against a working prototype, five of six requests were permission or access failures, so access is worth filtering for first.

GET /help

Source

fn resolve_help( &self, body: ResolveHelpRequest, ) -> impl Future<Output = Result<HelpResolved, Problem>> + Send

Mark help requests as dealt with.

Resolving says the blocker is gone, not I have read this. An agent that raises the same problem on its next run will raise it again, which is the point: a list that clears itself on being looked at stops being evidence of anything.

Narrow by agent, blocker or run. An empty body resolves every open request in the window, which is what you want after fixing something that stopped everything.

POST /help/resolve

Source

fn list_itineraries( &self, query: ListItinerariesQuery, ) -> impl Future<Output = Result<ItineraryList, Problem>> + Send

Chains of work, and what became of each.

A run is one agent doing one thing; an itinerary is the whole causal chain and the budget it shares. The distinction matters most when something goes wrong: a chain can be stalled — every run in it succeeded and nothing will ever happen again — and a list of runs cannot show that, because there is no failed run to point at.

GET /itineraries

Source

fn list_learnings( &self, query: ListLearningsQuery, ) -> impl Future<Output = Result<LearningList, Problem>> + Send

What agents have worked out, and how well established it is.

A learning applies as soon as it is proposed and expires unless later runs arrive at it independently. There is no approval queue, deliberately: a sibling project built one and after 22 days held 88 learnings, none ever approved, so not one had ever reached a run.

A learning becomes permanent through independent rediscovery, which is evidence, rather than through its impact rating, which is the agent’s own claim about its own work.

GET /learnings

Source

fn judge_learning( &self, path: JudgeLearningPath, body: JudgeLearningRequest, ) -> impl Future<Output = Result<Learning, Problem>> + Send

Settle a learning, either way.

This is not an approval queue. A learning applies from the moment it is proposed, and nothing is waiting on you. A sibling project gated learnings behind approval and after 22 days held 88 of them, none ever approved, so not one had ever reached a run.

This is the override. confirmed means “this is real, keep it indefinitely” and spares it from lapsing. rejected means “this is wrong, stop applying it” and takes it out of every future run. Both are judgements a person makes about something already in use, not permission for it to start being used.

PATCH /learnings/{learning_id}

Source

fn list_pipelines( &self, ) -> impl Future<Output = Result<PipelineList, Problem>> + Send

Every declared pipeline, its trigger and the flags it accepts.

GET /pipelines

Source

fn list_runs( &self, query: ListRunsQuery, ) -> impl Future<Output = Result<RunList, Problem>> + Send

Runs, live and historical.

GET /runs

Source

fn get_run( &self, path: GetRunPath, ) -> impl Future<Output = Result<Run, Problem>> + Send

One run, including how it ended.

GET /runs/{run_id}

Source

fn get_report( &self, path: GetReportPath, ) -> impl Future<Output = Result<Report, Problem>> + Send

What the agent wrote about this run.

A transcript is not a report: it contains every approach the agent abandoned, and reading one to find out what happened is slower than doing the work again. This is the agent’’s own account of what it concluded.

GET /runs/{run_id}/report

Source

fn stream_run( &self, path: StreamRunPath, ) -> impl Future<Output = Result<EventStream, Problem>> + Send

Live output from a run, as server-sent events.

GET /runs/{run_id}/stream

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§