Documentation
¶
Overview ¶
Package agents mounts the Hanzo Cloud /v1/agents surface: per-org autonomous agent definitions and their runs. An agent is a model + a system prompt (instructions) + a set of tool names; running one executes a real chat completion through the in-process AI client (the SAME gateway path the rest of the console uses) and records the run. Tenant isolation is the gateway-minted X-Org-Id (HIP-0026) enforced as the org column on every query, so one tenant can never read, run, or delete another's agents.
Surface (all org-scoped; console's AgentsModule reads {agents:[...]}):
GET /v1/agents list agents for the org -> {agents:[...]}
POST /v1/agents create an agent -> Agent
GET /v1/agents/:ref agent detail + recent runs -> AgentDetail
PATCH /v1/agents/:ref update an agent -> Agent
DELETE /v1/agents/:ref delete an agent (+ its runs)
POST /v1/agents/:ref/run run the agent {input} -> RunResult
GET /v1/agents/:ref/runs run history -> {runs:[...]}
:ref is either the agent's public id (the `agent_...` handle create and list return) OR its org-unique name — resolved by Store.Resolve, so a created agent is immediately gettable and runnable by whatever create/list handed back.
The store is SQLite in deps.DataDir (Base/SQLite-only). It holds definitions and run I/O only — never a secret; tool credentials live in KMS by reference.
Index ¶
- Constants
- func BillingActor(org, sub string) string
- func CloseSession(ctx context.Context, org, sessionID, status string) error
- func CountActiveSessions(ctx context.Context, org string, m SessionMatch) (int, error)
- func LogSessionEvent(ctx context.Context, org, sessionID, kind, actor string, payload []byte) error
- func Mount(app *zip.App, deps cloud.Deps) error
- func OfferRoutedRun(run RoutedRun) *offer
- func OpenSession(ctx context.Context, org, actor, agent, title string) (string, error)
- func OpenSessionOn(ctx context.Context, org, actor, agent, title, target string) (string, error)
- func Shutdown(ctx context.Context) error
- func StopSessions(ctx context.Context, org string, m SessionMatch) (int, error)
- func TargetDispatchable(ctx context.Context, org, targetID string) error
- type Agent
- type Event
- type GPU
- type Metrics
- type RoutedResult
- type RoutedRun
- type Run
- type Session
- type SessionFilter
- type SessionMatch
- type Spec
- type Store
- func (s *Store) AppendEvent(ctx context.Context, e Event) (Event, error)
- func (s *Store) ClaimKeyHash(ctx context.Context, org, targetID string) (hash string, servingAt int64, err error)
- func (s *Store) Close() error
- func (s *Store) CountChildren(ctx context.Context, org, id string) (int, error)
- func (s *Store) CountEvents(ctx context.Context, org, sessionID string) (int, error)
- func (s *Store) CountLongRunning(ctx context.Context, org string) (int, error)
- func (s *Store) CountRuns(ctx context.Context, org, agent string) (int, error)
- func (s *Store) Create(ctx context.Context, a Agent) error
- func (s *Store) CreateSession(ctx context.Context, x Session) error
- func (s *Store) CreateTarget(ctx context.Context, t Target) error
- func (s *Store) Delete(ctx context.Context, org, name string) (bool, error)
- func (s *Store) DeleteTarget(ctx context.Context, org, id string) (bool, error)
- func (s *Store) EventCountsByRoot(ctx context.Context, org, root string) (map[string]int, error)
- func (s *Store) Get(ctx context.Context, org, name string) (Agent, error)
- func (s *Store) GetSession(ctx context.Context, org, id string) (Session, error)
- func (s *Store) GetTarget(ctx context.Context, org, id string) (Target, error)
- func (s *Store) GetTargetByHost(ctx context.Context, org, host string) (Target, error)
- func (s *Store) InsertRun(ctx context.Context, r Run) error
- func (s *Store) LastEvent(ctx context.Context, org, sessionID string) (Event, bool, error)
- func (s *Store) List(ctx context.Context, org string) ([]Agent, error)
- func (s *Store) ListEvents(ctx context.Context, org, sessionID string, since int64, limit int) ([]Event, error)
- func (s *Store) ListLongRunning(ctx context.Context) ([]Agent, error)
- func (s *Store) ListRuns(ctx context.Context, org, agent string, limit int) ([]Run, error)
- func (s *Store) ListSessions(ctx context.Context, org string, f SessionFilter) ([]Session, error)
- func (s *Store) ListTargets(ctx context.Context, org string) ([]Target, error)
- func (s *Store) ListTree(ctx context.Context, org, root string, cap int) ([]Session, error)
- func (s *Store) Resolve(ctx context.Context, org, ref string) (Agent, error)
- func (s *Store) RunsSince(ctx context.Context, org string, since int64, limit int) ([]Run, error)
- func (s *Store) SessionLoad(ctx context.Context, org, id, host string) (TargetLoad, error)
- func (s *Store) StampServing(ctx context.Context, org, targetID string, now int64) error
- func (s *Store) TargetDispatchable(ctx context.Context, org, targetID string) error
- func (s *Store) Update(ctx context.Context, a Agent) error
- func (s *Store) UpdateSession(ctx context.Context, x Session) error
- func (s *Store) UpdateTarget(ctx context.Context, t Target) error
- func (s *Store) UpsertClaimKeyHash(ctx context.Context, org, targetID, hash string, now int64) error
- type Target
- type TargetLoad
- type TaskController
Constants ¶
const ( KindMessage = "message" KindToolCall = "tool-call" KindSpawn = "spawn" KindLog = "log" KindStatus = "status" KindControl = "control" )
Event kinds — the closed vocabulary of a session's ordered log.
const ( CmdPause = "pause" CmdResume = "resume" CmdStop = "stop" CmdMessage = "message" )
Control commands — the closed vocabulary of remote steering.
const ( StatusRunning = "running" StatusPaused = "paused" StatusDone = "done" StatusError = "error" )
Session status values. running/paused are live; done/error are terminal.
const ( ModeOneShot = "one-shot" ModeLongRunning = "long-running" )
Execution modes. One-shot agents run only on an explicit POST; long-running agents are additionally invoked by the scheduler on their Schedule.
const ( TargetLaptop = "laptop" TargetCloud = "cloud" TargetGPU = "gpu" TargetCluster = "cluster" TargetMachine = "machine" )
Target kinds — the closed vocabulary of dispatch destinations.
const ( TargetOnline = "online" TargetOffline = "offline" TargetDraining = "draining" )
Target status — a registered target is online until marked otherwise.
Variables ¶
This section is empty.
Functions ¶
func BillingActor ¶ added in v1.801.23
BillingActor is the exported form of the actor identity a session is recorded under. The login-manager adapter (the only external caller) uses it to scope a session stop/count to the REVOKING user's own actor, so a revoke can never reach a co-tenant's sessions. It mirrors what sessions.go stamps on Session.Actor, so a stop's actor predicate matches exactly the sessions that user created.
func CloseSession ¶ added in v1.801.23
CloseSession moves an org's session to a terminal state (done|error), stamping ended_at, and publishes the update. The store's monotonic-terminal rule already forbids reopening a finished run; here we only ever set a terminal status, so a double-close is a harmless no-op on an already-terminal row.
func CountActiveSessions ¶ added in v1.801.23
CountActiveSessions returns how many of org's sessions matching m are live (running|paused) — the device view's "active sessions". Org-scoped; 0 when not mounted or the match is empty.
func LogSessionEvent ¶ added in v1.801.23
LogSessionEvent appends one ordered event (message|tool-call|spawn|log|status| control) to an org's session and fans it out live. The (org, id) pair is re-resolved so a caller can only write to a session THIS org owns; kind is validated against the closed vocabulary and payload is size-bounded + must be well-formed JSON (nil payload is allowed for a bare marker). actor falls back to the org.
func OfferRoutedRun ¶ added in v1.801.79
func OfferRoutedRun(run RoutedRun) *offer
OfferRoutedRun is the exported seam the coding delivery activity uses to place a run into the live rendezvous. Kept here (agents owns targets + sessions) so the machine-facing HTTP surface and the durable activity share ONE mailbox.
func OpenSession ¶ added in v1.801.23
OpenSession registers a LIVE root session for org attributed to actor (an "org/sub" identity or a bare label) with the given agent label + title, and returns its id. The session is born running (not terminal like openRunSession's completed one-shot) so a long job streams status/log/tool-call events into it until CloseSession moves it to a terminal state. Best-effort live fan-out (publish) rides the bus; the store row is the truth.
func OpenSessionOn ¶ added in v1.801.79
OpenSessionOn is OpenSession with the run's dispatch TARGET recorded, so mission-control shows a routed run on the machine it was sent to (session.target == the target id) exactly as a locally-linked run shows its host. The target is re-resolved org-scoped and MUST belong to this org — a session can never claim to run on another tenant's machine (the same fail-closed rule sessionContext enforces on the HTTP register path). An empty target falls back to OpenSession.
func Shutdown ¶
Shutdown stops the scheduler (draining in-flight runs, bounded by ctx) and closes the agents store. Idempotent — safe to call when nothing is mounted.
func StopSessions ¶ added in v1.801.23
StopSessions closes every RUNNING|PAUSED session of org matching m — recording a control "stop" event on each and transitioning it to a terminal state — and returns how many it stopped. It is the action a login-out (link revoke) takes so the sessions that ran under a revoked account/device are torn down. Org AND Actor scope it: the caller passes their own actor (org/user), so a revoke can only ever stop the caller's OWN sessions — never a co-tenant's, never an org's every session — even though m's Host/Provider/Account come from an attacker-controllable link row. A match with no actor stops nothing (fail-closed). Not-mounted → (0, nil), so a revoke tolerates a deployment with no session plane.
func TargetDispatchable ¶ added in v1.801.79
TargetDispatchable is the exported gate the coding dispatcher injects (it never imports the store directly). Returns nil when a run may be routed to (org, targetID), else a descriptive error.
Types ¶
type Agent ¶
type Agent struct {
ID string
Org string
Name string
Model string
Instructions string
Description string
Tools []string
Status string
ExecutionMode string
Schedule string
ComputeRef string
ServiceAccountID string
CreatedAt int64
UpdatedAt int64
}
Agent is the org-scoped definition of an autonomous worker: a model, a system prompt (instructions), and a set of tool names it may call. Tenant isolation is the org column, enforced on every query. It never stores a secret — tool credentials live in KMS and are referenced by name at run time.
The bot-lifecycle fields promote an agent from a one-shot callable into a long-running bot (per hanzo-agent-bot-architecture: "Bot = Agent + compute + long-running"):
- ExecutionMode: "one-shot" (default; runs only when POSTed) or "long-running" (the scheduler invokes it on Schedule).
- Schedule: a 5-field cron expression; required when long-running, ignored otherwise. The scheduler evaluates it once a minute.
- ComputeRef: an optional visor machine id the bot is bound to. It is an opaque reference here; binding/lifecycle is owned elsewhere.
- ServiceAccountID: an optional IAM agent service-account (<org>-<agent>). When set it is the Actor recorded on scheduled-run billing so an autonomous run is attributable to a principal, not just the org.
func ListForOrg ¶ added in v1.786.112
ListForOrg returns the org's agents from the in-process store — the ONE exported seam other in-process subsystems use to read the canonical agent registry WITHOUT an HTTP hop back through the gateway.
It is the decompleced replacement for the old bots-as-members path, which enumerated agents over HTTP (/v1/agents with a forwarded bearer) and broke when HANZO_API_KEY was rejected (bot_members=0). clients/team calls this directly to project each agent as a workspace Employee.
ISOLATION: org is the ONLY tenant key and is used VERBATIM (Store.List filters WHERE org=?), so a caller for org A can never enumerate org B's agents. The caller MUST pass an org it already validated (principal.Org / a verified token claim), never a raw client header. Fails closed (nil, error) when the agents subsystem is not mounted or the org is empty/oversized.
type Event ¶ added in v1.786.32
type Event struct {
ID string
SessionID string
Org string
Seq int64
Kind string // message|tool-call|spawn|log|status|control
Actor string
Payload string // opaque JSON blob (validated well-formed, size-bounded)
CreatedAt int64
}
Event is one entry in a session's ordered log: a model message, a tool call, a subagent spawn, a free log line, a status change, or a control command the running surface consumes. Seq is monotonic PER SESSION so a subscriber can resume from its last-seen point; Org is denormalised so every read stays org-scoped without a join back to the session row.
type GPU ¶ added in v1.801.23
type GPU struct {
Vendor string `json:"vendor,omitempty"` // nvidia | amd | apple | intel | ...
Model string `json:"model,omitempty"` // "GB10", "8060S", "RTX 4090"
Memory int64 `json:"memory,omitempty"` // VRAM bytes, 0 = unknown
}
GPU is one accelerator on a machine.
type Metrics ¶ added in v1.801.23
type Metrics struct {
Load1 float64 `json:"load1,omitempty"`
Load5 float64 `json:"load5,omitempty"`
Load15 float64 `json:"load15,omitempty"`
MemUsed int64 `json:"memUsed,omitempty"` // bytes
MemFree int64 `json:"memFree,omitempty"` // bytes
GPUUtil float64 `json:"gpuUtil,omitempty"` // 0..1 aggregate utilization
At int64 `json:"at,omitempty"` // unix seconds, server-stamped
}
Metrics is a machine's live state from the last heartbeat.
type RoutedResult ¶ added in v1.801.79
type RoutedResult struct {
OK bool `json:"ok"`
Changed bool `json:"changed"`
Branch string `json:"branch,omitempty"`
CommitSha string `json:"commitSha,omitempty"`
Diffstat string `json:"diffstat,omitempty"`
Error string `json:"error,omitempty"`
}
RoutedResult is a routed run's terminal outcome, reported by the machine and returned to the durable activity so the workflow completes.
type RoutedRun ¶ added in v1.801.79
type RoutedRun struct {
Org string `json:"org"`
TargetID string `json:"targetId"`
SessionID string `json:"sessionId"` // the live session opened at dispatch; the machine streams into it
Repo string `json:"repo"`
Project string `json:"project,omitempty"`
Base string `json:"base,omitempty"`
Branch string `json:"branch"`
Prompt string `json:"prompt"`
CloneURL string `json:"cloneUrl"`
TimeoutSeconds int `json:"timeoutSeconds,omitempty"`
}
RoutedRun is the NON-SECRET spec of one coding run dispatched to a target. It carries no credential by design: the executing machine authenticates git + model routing with its OWN already-held credentials (the same ones `hanzo code` uses), so no secret ever enters the durable store or crosses to the machine in the claim response. Everything here is safe to persist in the tasks engine.
type Run ¶
type Run struct {
ID string
Org string
AgentName string
Status string
Model string
Input string
Output string
Error string
DurationMs int64
CreatedAt int64
}
Run is one execution of an agent: the input, the produced output (or error), which model served it, and how long it took. Real history — every row is a call that actually happened.
func RunOnBehalf ¶ added in v1.786.82
RunOnBehalf runs agent `ref` for `org` ON BEHALF OF `userSub`, IN-PROCESS — no gateway hop, no Cloudflare/IPv6 exposure. It is the clean in-process twin of the HTTP s.run handler: the CALLER (e.g. the Slack integrations bridge) has ALREADY authenticated org+userSub server-side, so this entry takes them DIRECTLY and never reads an HTTP principal / JWT / zip.Ctx. It resolves the agent org-scoped, runs it through the SAME runAgent → executeRun → meter path as s.run (one run path: one balance gate, one debit, one recorded run, one live session), and bills billingActor(org, userSub) against ORG's ledger.
ISOLATION: org is the ONLY tenant key. Store.Resolve is org-scoped, so a caller for org A can never resolve, run, or bill against org B's agent — exactly the property the HTTP handler relies on the gateway-minted X-Org-Id for.
A non-nil error means NO run happened: not mounted, invalid org, oversized input, inference not configured, agent-not-found (errNotFound), or a balance-gate denial (out-of-funds / commerce-unknown). A run that executed but whose model failed returns a recorded error-status Run and a nil error.
type Session ¶ added in v1.786.32
type Session struct {
ID string
Org string
Agent string // agent name / type label (need not be a cloud Agent row)
Actor string // the principal that started it (validated user, or a bound SA)
Status string // running|paused|done|error
ParentID string // "" for a root (the outer agent)
RootID string // the tree key; == ID for a root
Title string
StartedAt int64
EndedAt int64 // 0 until a terminal status is reached
CreatedAt int64
UpdatedAt int64
// TaskWorkflowID / TaskRunID link this session to the hanzoai/tasks durable
// workflow that actually EXECUTES it. This registry is the view/control/stream
// layer; durable execution (retries, resumability, scheduling) is owned by
// hanzoai/tasks — NOT by a bespoke scheduler here. A root session maps to a
// tasks workflow (ExecuteWorkflow); a subagent maps to a child workflow keyed
// by the same RootID. When these are set, control (pause/resume/stop/message)
// forwards to the tasks Signal/Cancel API (see State.tasks). Empty = a surface
// that consumes control from the event stream instead (today's @hanzo/dev).
TaskWorkflowID string
TaskRunID string
// Execution context — WHERE this session runs. All optional (a surface that
// doesn't know sets ""), surfaced by mission-control so a card shows the
// machine/repo/cwd it runs on and the devices view maps "which sessions run
// where". Host is the machine label; Repo/Cwd are the code context; Target is a
// registered run-target id (the #48 dispatch association — resolved same-org at
// register/patch so it never points across tenants). Truth the SURFACE reports.
Host string
Cwd string
Repo string
Target string
// Provider/Account tag a session with the linked AI account it ran under (the
// login-manager tie-in): which provider (claude|codex|hanzo|…) and which
// subscription/api account served this run. Optional (a surface that doesn't
// know sets ""), surfaced so the cockpit shows "this ran on your Claude Max
// acct" and so a login-out (link revoke) can stop the sessions that used it.
Provider string
Account string
}
A live agent-session is a running invocation — a cloud agent run, a bot loop, or a @hanzo/dev CLI run spawning subagents. The SUBAGENT TREE is sessions linked by ParentID: the outer agent is the root (ParentID==""), each spawned subagent is a child, and RootID is the tree key every node in one flow shares. It is the first-class, streamable form of the blue/red/cto fan-out tree.
A session is NOT foreign-keyed to an agents row: an external surface (the @hanzo/dev CLI) registers a session whose Agent is just a label, not a cloud Agent definition. Tenant isolation is the Org column, enforced on every query exactly like agents/runs — one file (agents.db), tenancy is the org.
type SessionFilter ¶ added in v1.786.32
SessionFilter selects a slice of an org's sessions. The fields are AND-ed; a zero field is "any". Scope picks the structural axis:
- Root set -> every session in that tree (root_id == Root).
- Parent set -> the direct children of Parent (parent_id == Parent).
- neither -> roots only (parent_id == ”), the outer-agent view.
type SessionMatch ¶ added in v1.801.23
SessionMatch selects live (running|paused) sessions to stop or count. Actor (the owning subject, org/user) is MANDATORY and always ANDed, so a match can only ever affect the caller's OWN sessions — never a co-tenant's. Host/Provider/Account are optional narrowing WITHIN the actor's sessions (empty = any of the actor's). A match with no actor selects NOTHING (fail-closed), so a login-out can never sweep another user's — or an org's every — session, even when Host/Provider/Account are attacker-set at link upsert.
type Spec ¶ added in v1.801.23
type Spec struct {
OS string `json:"os,omitempty"` // linux | darwin | windows
Arch string `json:"arch,omitempty"` // amd64 | arm64 | ...
CPUs int `json:"cpus,omitempty"` // logical cores
Memory int64 `json:"memory,omitempty"` // total RAM, bytes
GPUs []GPU `json:"gpus,omitempty"`
}
Spec is a machine's static capability.
func (Spec) Sanitize ¶ added in v1.801.23
Sanitize bounds every field so a target row stays small and well-formed no matter what a client sends: strings trimmed + length-capped, counts/sizes non-negative and clamped, GPU list truncated, floats coerced finite. It is total (never errors) so the write path can always proceed with a safe value.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the agents database. ONE SQLite file ({DataDir}/agents.db) holds every org's records; tenancy is the org column.
func (*Store) AppendEvent ¶ added in v1.786.32
AppendEvent inserts one event, allocating the next per-session Seq. The store runs on a single connection (SetMaxOpenConns(1)) so the read-then-write of the max seq is serialised; the UNIQUE(session_id,seq) index is the final backstop. The session's updated_at is bumped in the SAME transaction so "last activity" stays truthful. Returns the persisted event (with Seq/CreatedAt) for streaming.
func (*Store) ClaimKeyHash ¶ added in v1.801.79
func (s *Store) ClaimKeyHash(ctx context.Context, org, targetID string) (hash string, servingAt int64, err error)
ClaimKeyHash returns a target's stored hash + last serving stamp, or errNoClaimKey when none was ever minted.
func (*Store) CountChildren ¶ added in v1.786.32
CountChildren returns how many DIRECT children a session has (its fan-out).
func (*Store) CountEvents ¶ added in v1.786.32
CountEvents returns how many events a session has (the list rollup).
func (*Store) CountLongRunning ¶ added in v1.786.32
CountLongRunning returns how many scheduled long-running agents an org has — used to cap an org's scheduler footprint at create time.
func (*Store) Create ¶
Create inserts one agent. A UNIQUE(org,name) violation surfaces as errConflict.
func (*Store) CreateSession ¶ added in v1.786.32
CreateSession inserts one session. When ParentID is set it MUST reference an existing session IN THE SAME ORG — the caller resolves it via GetSession first so a cross-tenant or dangling parent can never link a tree. RootID is derived by the caller (parent's root, or self for a root); this method persists what it is given after a final same-org sanity check on the parent.
func (*Store) CreateTarget ¶ added in v1.801.23
CreateTarget inserts one target. The id is caller-generated (genID("tgt")).
func (*Store) DeleteTarget ¶ added in v1.801.23
DeleteTarget removes an org's target. Sessions keep their recorded target id (a historical fact); a detached target simply stops appearing in the registry.
func (*Store) EventCountsByRoot ¶ added in v1.786.32
EventCountsByRoot returns per-session event counts for EVERY session in one org's tree (root_id == root) in a SINGLE grouped query — so materialising a tree of N nodes with real per-node event counts costs one round trip, not N, and never hits SQLite's bound-parameter limit (the join scopes by root_id, not an IN list of ids).
func (*Store) Get ¶
Get returns the agent for the exact (org,name) or errNotFound. It is the precise name primitive; path-addressed handlers use Resolve (id-or-name).
func (*Store) GetSession ¶ added in v1.786.32
GetSession returns the (org,id) session or errSessionNotFound. The org is part of the key so one tenant can never resolve another's session id.
func (*Store) GetTarget ¶ added in v1.801.23
GetTarget returns the (org,id) target or errTargetNotFound. Org is part of the key so one tenant can never resolve another's target id.
func (*Store) GetTargetByHost ¶ added in v1.801.23
GetTargetByHost returns an org's target reporting the given host, or errTargetNotFound. It is how a re-link of the SAME machine finds its existing target (idempotent register) instead of creating a duplicate. Org-scoped: a host string can never resolve another tenant's target. Newest wins if a host was ever double-listed.
func (*Store) LastEvent ¶ added in v1.801.23
LastEvent returns a session's most recent event (highest seq) — the one-line "last activity" a mission-control card shows in the list without fetching full detail. ok=false when the session has no events yet. Org-scoped like every read.
func (*Store) ListEvents ¶ added in v1.786.32
func (s *Store) ListEvents(ctx context.Context, org, sessionID string, since int64, limit int) ([]Event, error)
ListEvents returns a session's events in Seq order (optionally only those with Seq > since, so a subscriber resumes exactly where it dropped), capped.
func (*Store) ListLongRunning ¶ added in v1.786.32
ListLongRunning returns every agent across ALL orgs whose execution_mode is long-running and that carries a non-empty schedule — the scheduler's work set. It is the ONE cross-org query in this store; the scheduler is a trusted in-process subsystem (not a tenant request), and each returned agent carries its own Org so every downstream action (run, gate, meter) stays scoped to the agent's own tenant.
func (*Store) ListSessions ¶ added in v1.786.32
ListSessions returns an org's sessions per filter, newest first, capped.
func (*Store) ListTargets ¶ added in v1.801.23
ListTargets returns an org's targets, newest first.
func (*Store) ListTree ¶ added in v1.786.32
ListTree returns EVERY session in one org's tree (root_id == root), oldest first so a caller can assemble parent→child in a single pass. Capped so a pathological tree can't produce an unbounded response.
func (*Store) Resolve ¶ added in v1.786.32
Resolve returns the agent identified by ref within org, matching either its public id (the `agent_...` handle create and list hand back) OR its org-unique name. This is the ONE lookup every path-addressed handler (get/update/delete/ run/runs) uses, so a just-created agent is immediately addressable by exactly the identifier create/list returned — no id-vs-name split. If a ref somehow equals one agent's id and another's name, the id match wins (the stable public handle is authoritative). Tenancy is the org filter, so a ref belonging to another tenant is errNotFound — fail-closed, never cross-org.
func (*Store) RunsSince ¶ added in v1.786.32
RunsSince returns the org's runs across ALL agents with created_at >= since, newest first, capped. It powers the org-wide surfaces: the recent-activity feed (since=0 → the newest runs regardless of age) and the invocation histogram (since=windowStart → every run in the window, order-independent for bucketing). since<=0 means "no lower bound". Tenancy is the org column, so a caller never sees another org's runs. Every row is a real recorded execution.
func (*Store) SessionLoad ¶ added in v1.801.23
SessionLoad returns how many of an org's sessions are mapped to a target: those explicitly dispatched to it (target == id) OR reporting its host (host == host, when the target has a host). One exact query (no double count) per target — the list is small so the per-row cost matches the sessions list's own rollups.
func (*Store) StampServing ¶ added in v1.801.79
StampServing records that a target's runner polled at now (its liveness heartbeat). Best-effort by the caller; a missing row is a no-op.
func (*Store) TargetDispatchable ¶ added in v1.801.79
TargetDispatchable is the DRY liveness gate, used at dispatch (fail closed before enqueue) AND re-checked at claim. A run is dispatchable only to a target that (a) exists in this org, (b) is online, and (c) has a live runner — a claim poll within servingTTL. Any failure is an explicit error the dispatcher renders honestly; it NEVER falls back to running elsewhere.
func (*Store) UpdateSession ¶ added in v1.786.32
UpdateSession persists status/title/ended_at for an existing (org,id) session. Scoped by org so a cross-tenant id can never mutate another's session.
func (*Store) UpdateTarget ¶ added in v1.801.23
UpdateTarget persists mutable fields for an existing (org,id) target. Scoped by org so a cross-tenant id can never mutate another's target.
func (*Store) UpsertClaimKeyHash ¶ added in v1.801.79
func (s *Store) UpsertClaimKeyHash(ctx context.Context, org, targetID, hash string, now int64) error
UpsertClaimKeyHash stores (or rotates) a target's claim-key hash. serving_at is reset to 0 on a fresh mint — the daemon proves liveness by its first poll.
type Target ¶ added in v1.801.23
type Target struct {
ID string
Org string
Label string
Kind string // laptop | cloud | gpu | cluster | machine
Status string // online | offline | draining
Capacity string // free-form ("8 vCPU / 32G", "1× GB10") — human summary
Host string // hostname sessions on this machine report (maps sessions -> target)
Spec Spec // static capability
Metrics Metrics
MetricsAt int64
CreatedAt int64
UpdatedAt int64
}
Target is a registered agent run-target. Owned by one org. Spec is its static capability (os/arch/cpus/memory/gpus) and Metrics its last live heartbeat (loadavg/memory/gpu-util); MetricsAt is the unix second that heartbeat was recorded (0 = never). See targetspec.go for the value plane.
func ResolveTarget ¶ added in v1.801.79
ResolveTarget resolves a human's target REFERENCE — a target id or its friendly label (the hostname the CLI registers) — to the org's target, org-scoped and fail-closed. It is the ONE way a trigger surface (the Slack `code: <repo> on <target>` grammar, a console picker) turns "on evo" into a target id without leaking another tenant's inventory: an id or label that resolves to no target in THIS org returns errTargetNotFound, never another org's machine.
Precedence: an exact id match wins (ids are unambiguous), else an exact, case-folded label match (newest first, so a re-registered machine's live row is preferred). A reference that matches neither is not found — the caller renders an honest error and NEVER falls back to a local run.
type TargetLoad ¶ added in v1.801.23
type TargetLoad struct {
Sessions int // total sessions mapped to the target
Running int // of those, how many are currently running
}
TargetLoad is the live session load on a target.
func LoadOn ¶ added in v1.801.59
func LoadOn(ctx context.Context, org, id, host string) (TargetLoad, error)
LoadOn returns the live session load on one of the org's targets — the same (target id OR host) mapping the HTTP views use, so the board and /v1/agents/ targets can never disagree about what is running where.
type TaskController ¶ added in v1.786.32
type TaskController interface {
// Signal forwards a cooperative control signal (pause/resume/message) to the
// durable workflow backing a session. name is the signal name; payload is the
// opaque signal argument (e.g. a steer message), nil when there is none.
Signal(ctx context.Context, workflowID, runID, name string, payload []byte) error
// Cancel gracefully cancels the durable workflow backing a session (a stop).
Cancel(ctx context.Context, workflowID, runID, reason string) error
// Enabled reports whether a real tasks backend is wired. When false the
// control endpoints record the intent and skip the forward (honest degrade,
// same pattern as deps.AI).
Enabled() bool
}
TaskController is the seam to the hanzoai/tasks durable-execution engine — the ONE canonical engine for durable/retriable/scheduled agent work. This sessions surface is the REGISTRY + control + ZAP-stream VIEW layer; it deliberately owns NO scheduler, ticker, or lease. When a session is backed by a tasks workflow (Session.TaskWorkflowID set), a control command forwards through this seam to the engine's signal/cancel API instead of only being recorded.
The method set mirrors github.com/hanzoai/tasks/pkg/sdk/client.Client exactly, so the live adapter is a thin wrapper (Signal→Client.SignalWorkflow, Cancel→Client.CancelWorkflow) with no impedance mismatch:
SignalWorkflow(ctx, workflowID, runID, signalName string, arg any) error CancelWorkflow(ctx, workflowID, runID string) error
TASKS PLUG-IN POINT. The live controller is wired in Mount from a dialed tasks client (client.Dial(TASKS_URL)); until the hanzoai/tasks native engine lands (today its workflow opcodes return 501 by design — "the shape is in place so callers depend on the API while the engine lands behind it"), the default is the disabled controller: control is still durably RECORDED as a session event for stream-consuming surfaces, and the forward is a clean no-op.