Skip to content

SDK reference ​

hmz.sdk: the supported import path for programs that drive Humanize. It defines nothing of its own but Daemons; every other name is the object the runtime or the daemon layer holds, handed through unchanged. Notation: Conventions.

python
from hmz.sdk import Hmz, Daemons, Refused, fakes

Module ​

python
__all__ = ["Accounts", "Daemon", "Daemons", "Epics", "Fallbacks", "Flows", "Flowverses", "Hmz",
           "Host", "Link", "Refused", "Run", "Runtimes", "fakes"]
def __getattr__(name: str) -> object: ...
NameKindDefined inSection
Hmzclasshmz.runtimeHmz
Runclasshmz.runtimeRun
Refusedexceptionhmz.runtimeRefused
Flowsclasshmz.runtimeFlows
Flowversesclasshmz.runtimeFlowverses
Accountsclasshmz.runtimeAccounts
Runtimesclasshmz.runtimeRuntimes
Fallbacksclasshmz.runtimeFallbacks
Epicsclasshmz.runtimeEpics
Hostclasshmz.runtimeHost
Daemonsclasshmz.sdk.daemonsDaemons
Daemonfrozen dataclasshmz.daemonDaemon
Linkclasshmz.daemonLink
fakesmodulehmz.runtime.flowing.fakesfakes
Rule
LazyEach name is imported from its layer on first access (module __getattr__). import hmz.sdk imports nothing else.
Identityhmz.sdk.X is <layer>.X: the same class, not a wrapper.
Unknown namesAttributeError: module 'hmz.sdk' has no attribute '<name>'.
fakesA module attribute: from hmz.sdk import fakes works; import hmz.sdk.fakes raises ModuleNotFoundError.
StabilityNames in __all__ are stable. Types they return that are not in __all__ (Line, Offer, Declaration, Provider, …, listed under Returned types) are internal: their fields are documented as they are.

Hmz ​

python
class Hmz:
    def __init__(self, workspace: str | os.PathLike[str] | None = None) -> None

One workspace and everything Humanize can be asked to do in it. The constructor loads nothing.

ParameterTypeDefaultMeaning
workspacestr | PathLike | NoneNoneThe project directory. None: the current directory, re-read at each use. Kept as given; ~ is not expanded.

Properties ​

PropertyTypeValue
workspacePathThe project directory.
homePath$HUMANIZE_HOME, else ~/.hmz (a ~/.humanize is moved there). Not created.
settingshmz.runtime.settings.SettingsWhat is remembered for this workspace and machine (Settings). Internal type.
flowsFlows
versesFlowversesThe same object as flows.verses.
accountsAccounts
runtimesRuntimes
fallbacksFallbacks
epicsEpicsOf this workspace.

workspace and home are computed on each access; the others are created on first access and cached on the instance.

Methods ​

MethodReturnsRaises
run(flow, task, *, …)RunRefused
runner(flow, *, …)RunnerRefused
read(argv)LineSystemExit
exec(argv)AnySystemExit, Refused, what the flow raises
host(slot="")HostValueError
backends()tuple[Profile, ...]—
reports()bool—
  • host(slot=""): a Host of this workspace, created on first call with that slot and cached on the instance. Frontends attached to it share one run. slot is "" for the workspace's own, or chat:<hex> for one chat's; anything else raises ValueError.
  • backends(): every coding-agent CLI Humanize drives, installed or not, as internal hmz.coganchor.backends.Profile objects (.name, .aliases, .efforts, .installs, …). [p.name for p in Hmz().backends()] is ['claude', 'agy', 'codex', 'dsh', 'grok', 'kimi', 'pi', 'omp', 'qwen', 'opencode', 'mimo', 'cursor-agent', 'mcode', 'litellm'].
  • reports(): starts error reporting where it has been answered yes (or HUMANIZE_SENTRY=on). Returns whether anything is being reported. Never asks.

Hmz.run ​

python
def run(
    self,
    flow: str | os.PathLike[str],
    task: str,
    *,
    agents: Mapping[str, str | AgentDriver] | Iterable[AgentSpec] = (),
    envs: Mapping[str, str | EnvDriver] | Iterable[EnvSpec] = (),
    params: Mapping[str, Any] | FlowParams | None = None,
    budget: Budget | Mapping[str, Any] | None = None,
    profile_flow: bool = False,
    profile_environment: bool = False,
    resume: bool | str | os.PathLike[str] = False,
    outworlder: OutworlderDriver | None = None,
) -> Run

Equivalent to Run(self.runner(flow, agents=…, envs=…, params=…, budget=…, profile_flow=…, profile_environment=…, resume=…), task, outworlder=outworlder). Nothing starts. Where each agent's harness runs is not a parameter: it is the harness setting of the runtime its work is on.

ParameterAcceptsDefault
flowA -f ref or a path.—
taskThe task text.—
agents{role: spec} where spec is an -a spec without <role>= ("claude@work/claude-opus-5:high") or an AgentDriver (e.g. fakes.FakeAgentDriver); or an iterable of AgentSpec (Line.agents).()
envs{role: spec} with an -e spec without <role>=, or an EnvDriver; or an iterable of EnvSpec.()
paramsA mapping (strings read as -p reads them) or an instance of the flow's FlowParams. None: defaults.None
budgetA Budget, or a mapping validated by Budget.model_validate ({"cost": 5}, {"duration": 3600}, {"duration": "PT1H"}; "1h" is not accepted). None: Budget(cost=inf) for chat, else refused.None
profile_flowWhether to profile the flow's own Python, as well as tracing the run; as --profile-flow.False
profile_environmentWhether to profile the programs the run's agents start, as well as tracing them; as --profile-environment.False
resumeFalse: from the top. True: the newest resumable epic of this flow here. A path: that epic.False
outworlderThe driver filling Outworlder roles (e.g. fakes.FakeOutworlder). None: always away, as under hmz exec.None

Raises Refused for everything hmz exec refuses at stage 3, in the same words, plus:

ConditionMessage
a role given twice across a mapping and specs<flow>: duplicate agent role '<role>' / … environment role …
an invalid budget mappingthe budget is invalid: <pydantic error>
a resume path with no journal entry<epic name> has no saved progress to resume from
python
from hmz.sdk import Hmz, Refused

try:
    Hmz().run("goal", "fix the build", agents={"worker": "pi/gpt-5.5:high"}, budget={"cost": 5})
except Refused as why:
    print(why)   # goal: 'worker' needs GoalCommandAgentMixin, which pi does not support

Hmz.runner ​

python
def runner(self, flow, *, agents=(), envs=(), params=None, budget=None, profile_flow=False,
           profile_environment=False, resume=False) -> Runner

Parameters and refusals as run, without task and outworlder. Returns the internal hmz.runtime.runner.Runner: the flow loaded (its module imported), a driver made for every role, everything checked. Making a driver starts no CLI and reaches no machine.

Hmz.read ​

python
def read(self, argv: list[str]) -> Line

Parses an hmz exec argument list (without exec) to a Line. Loads no flow. A line argparse rejects, or an -a/-e/-p that does not parse, prints usage and the error to stderr and raises SystemExit(2); --help prints help and raises SystemExit(0).

python
hmz = Hmz()
line = hmz.read(["-f", "ralph_loop", "-a", "agent=claude/claude-opus-5:high",
                 "-p", "budget.duration=6h,budget.cost=50", "fix the build"])
run = hmz.run(line.flow, line.task, agents=line.agents, envs=line.envs,
              params=line.params, budget=line.budget, profile_flow=line.profile_flow,
              profile_environment=line.profile_environment, resume=line.resume)

Hmz.exec ​

python
def exec(self, argv: list[str]) -> Any

read(argv), then run(…), then Run.run(). Returns what the flow returned. Unlike the hmz exec command it draws nothing, installs no signal handlers and does not convert Refused or BudgetExceeded into an exit status.

Run ​

python
class Run:
    def __init__(self, runner: Runner, task: str, *,
                 outworlder: OutworlderDriver | None = None) -> None

One run of one flow. Made by Hmz.run. Constructing one starts nothing.

Properties ​

PropertyTypeValue
flowstrThe flow as named.
refstrIts canonical ref (chat:chat, humanize1:rlcr).
taskstr
declarationDeclarationWhat the flow declares.
budgetBudgetWhat the run may spend.
profile_flow, profile_environmentboolWhether the run's flow, and the programs its agents start, are profiled as well as traced.
usagehmz.flows.UsageSpent so far: duration: timedelta, cost: float, output_tokens: int.
agentstuple[AgentBase, ...]The coganchor agent behind each open session, oldest first. Empty for fake drivers.
epicPath | NoneThe epic directory, once started.
runningboolWhether a run started with start() (or run() from a thread already running an event loop) is still going. Always False for run() on a thread without a loop.
raisedBaseException | NoneFor a run started with start() and over: what the flow raised (asyncio.CancelledError after stop()).
resultAnyFor a run started with start() and over: what the flow returned.

Methods ​

MethodReturnsBehaviour
run()AnyRuns the flow on an event loop in this thread until it returns; returns its result or raises what it raised. From a thread already running an event loop, runs on a new thread and waits. Raises Refused before the flow is called if an environment cannot be reached or is too small.
start()NoneRuns it on a new thread and returns at once. RuntimeError if already started.
wait(timeout: float | None = None)boolBlocks until the run ends or timeout seconds pass; returns whether it ended.
stop()NoneInterrupts the turn under way; every flow call raises CancelledError where it stands; sessions are closed and temporary directories removed as the flow unwinds. Thread-safe. Does not wait.
close()Nonestop(), then closes every open session and agent at once. The flow sees a failed turn.
unreadable()strThe budget cap nothing driven can enforce, in words (the hmz exec note), or "". A finite cost limit first brings a missing or stale price list up to date (at most 20 s), as run and start do. Raises Refused if the price list gives a price that is not a finite number.
watch(listener)NoneRegisters listener(agent: AgentBase, session: SessionBase | None, event: Event), called for every event of every session from the thread that read it. Watching also stops CLIs writing their own progress to this process's streams.
noticed(callback)NoneRegisters callback(text: str), called on the run's loop with Humanize's own word about the run before the flow is called: an environment moved down its runtime's fallback list (docker:a cannot hold 'box': <why>; using docker:b).
opened(callback)NoneRegisters `callback(role: str, agent: AgentBase, session: SessionBase, where: Placement

AgentBase, SessionBase and Event are coganchor's (Agents).

Refused ​

python
class Refused(ValueError): ...

A run, or a request to a host, refused before anything of it ran. str(error) is the message hmz exec prints after hmz exec: error: , and the reason a host gives every frontend. __cause__ is the underlying exception where there was one (FlowException, SpecError, pydantic.ValidationError).

Flows ​

Hmz().flows. Constructor: Flows().

MemberReturnsBehaviour
versesFlowversesProperty.
all()list[Offer]Every runnable flow, in offer order.
find(named: str)strThe resolved file of a flow, or "" where nothing resolves. A path starts with ., / or ~; anything else is a name, never a file of that name in the working directory.
about(named: str)strThe flow's one-line description, or "".
declared(named: str | PathLike)DeclarationA str as -f reads it; a PathLike always a path, ./'d where it is relative. Imports the flow. Raises the flow API's FlowException for a flow that cannot load.
resumes(named: str | PathLike)boolWhether it is resumable. Imports the flow.
fork(named: str, into: str | PathLike | None = None)strCopies the flow, what it imports and its skills into ./.hmz/flows/ (or into), as Copy here does in /flow; not an installed flow's .installed.json. Returns the directory. ValueError: not a flow, or already a copy here. OSError: cannot copy.
running()tuple[LiveCall, ...]Every flow call in progress in this process, oldest first.
python
for offer in Hmz().flows.all():
    print(offer.name, "·", offer.about)

Flowverses ​

Hmz().verses: the store /flow's Flowverses page edits. flow arguments are the name a flow is offered under: <flow> or <user>/<flow> for official's, @<flowverse>/<flow> or @<flowverse>/<user>/<flow> for another's. index() takes a flowverse's bare name, and its methods a flow by index name (<flow>, <user>/<flow>). Semantics: Flows › Flowverses.

MethodReturnsBehaviour
all()list[Flowverse]Offer order: official, added ones alphabetically, local, user.
nearest()list[Flowverse]Lookup order for a bare name: local, user, official, added ones.
find(name: str)Flowverse | None
add(url: str, name: str = "")FlowverseClones the index at url (a URL, a path, or owner/repo on GitHub) under name (default: the repository's name). Installs nothing. ValueError: name taken, reserved (official, local, user) or not a valid directory name. OSError: clone failed.
fetch(name: str)FlowverseFetches the index again, or for the first time; resets the clone to the remote. Installed flows are untouched. ValueError: no such name, or local/user. OSError: git failed.
remove(name: str)boolDeletes the index and every flow installed from it; whether there was one. ValueError: official, local, user.
index(name: str)IndexWhat its index lists, as last fetched. Reads YAML only; empty for local, user, an unfetched one or an unknown name.
install(flow: str, version: str = "")list[Installed]Installs that release ("": the newest that is not a prerelease, else the newest prerelease) and what it needs. Returns what is now installed of every flow the install came to, the asked-for one last. Another version of an installed flow switches it. ValueError: no such flowverse, flow or release; unfetched; a cycle; a range nothing satisfies; breaking another installed flow's range. OSError: fetch or copy failed.
uninstall(flow: str)boolRemoves an installed flow; whether there was one. ValueError: another installed flow needs it. OSError: it will not go.
installed()list[Installed]Every installed flow, by flowverse and then name.
updates()list[Update]Every installed flow whose index, as last fetched, lists a newer release.
holds(one: Flowverse)list[Offer]What it offers to run: built-in and installed flows for official, installed ones for another, the directory's for local and user. Imports every flow in it. Never a flow its index only lists.
edited(one: Flowverse)boolWhether the clone holds changes a fetch would discard. False for a non-clone.
standing(one: Flowverse)strThe clone's commit, or "".
where(name: str)PathIts index's directory, fetched or not.
plain(url: str)strurl with credentials removed.
whence(one: Flowverse, nowhere: str = "-")strDisplayable origin: the credential-free URL; your own flows in .hmz/flows for local, your own flows in ~/.hmz/flows for user; nowhere for a directory with no readable origin.
python
from hmz.sdk import Hmz

verses = Hmz().verses
verses.fetch("official")
for release in verses.index("official").versions("flame_chasoid"):
    print(release.version, release.commit[:12])
verses.install("flame_chasoid")
for update in verses.updates():
    print(update.installed.called, update.installed.version, "->", update.version)

Accounts ​

Hmz().accounts: provider accounts. cli accepts any name or alias of a backend. An account name of "" is the machine's own login (as local).

MethodReturnsBehaviour
all(cli: str = "")list[Provider]Every account, or one backend's; by backend, then name.
find(cli: str, name: str)Provider | None
ways(cli: str)tuple[Way, ...]How the backend can be signed into, in offer order (for claude: login, console, token, key, wif, anthropic-gateway, bedrock-gateway, vertex-gateway, bedrock, bedrock-key, mantle, vertex, foundry, aws, google-cloud, env).
way(cli: str, name: str)Way | None
asks(way: Way, given: Mapping[str, str])list[str]Variables still unanswered.
make(cli, name, way: Way, answers=None)ProviderWrites an account from a way's answers; makes its directory. ValueError: bad backend or name. OSError.
sign_in(provider, way, answers=None)intRuns the backend's sign-in command under the account's paths; its exit status.
write(cli, name, way="", env=None, args=())ProviderWrites an account as given, replacing env/args, keeping credentials. With args empty, a named way that adds arguments (codex's openai-gateway) has them filled from env. ValueError, OSError.
where(cli, name)PathIts credentials directory. ValueError: unknown backend or invalid name.
serves(one: Provider)tuple[str, ...]Other backends its credentials could run.
copies(one, cli, name="")ProviderWrites the same account for another backend. ValueError: that backend cannot use it.
remove(cli, name)boolDeletes an account and its credentials. ValueError for "".
env(said: str)dict[str, str]Parses NAME=VALUE lines.
environ(provider: Provider | None)dict[str, str]The environment a turn under it gets; {} for None.
models(cli, provider="")tuple[Model, ...]What the backend last reported it runs as this account; () if never asked.
asked(cli, provider="")strWhen that was, or "".
stale(cli, provider="")boolNever asked, or asked longer ago than hmz.coganchor.models.STALE (one week).
ask(cli, provider="", seconds=None)tuple[Model, ...]Starts the backend to list its models, and keeps the answer. () if it does not answer.

Runtimes ​

Hmz().runtimes: saved runtimes, named by -e <role>=ssh@<name> and -e <role>=docker@<name>. backend is "ssh" or "docker".

MethodReturnsBehaviour
all(backend: str = "")list[Runtime]By backend, then name.
find(backend, name)Runtime | None
where(backend, name)PathWhere it is kept. ValueError: bad backend or name.
new(backend, name, **fields)RuntimeBuilds and validates one; saves nothing. ValueError: unknown field or bad value. new(**p.held()) equals p. harness="docker:gpubox" (default "env"; also "local") sets where the harness of work on it runs (Remote execution › The harness setting).
add(runtime)RuntimeSaves a new one. ValueError: name taken. OSError.
write(runtime)RuntimeSaves, replacing any of that name. OSError.
remove(backend, name)boolValueError: bad backend or name.
hosts(config: str | PathLike | None = None)list[SSHHost]Every Host in an ssh config (default ~/.ssh/config), as ssh -G resolves it. OSError: no ssh, unreadable config.
import_ssh(config=None, names=None, *, update=False)list[SSHRuntime]Saves one ssh runtime per Host (or per name in names), named after it; existing ones kept unless update. ValueError: a name not in the config.
resolve(runtime: SSHRuntime)SSHHostWhat ssh -G makes of it; reaches nothing.
check(runtime, seconds: float = 30.0)CheckedReaches it: an ssh host for home, CPUs, memory, GPUs; a docker daemon via docker info. Never raises.

Fallbacks ​

Hmz().fallbacks: fallback chains between places, each spelled <cli>[@<account>]/<model>. A chain is written against one place, its main, and lists the places tried after it, in order.

MemberReturnsBehaviour
defaultstrProperty: "exponential-jitter".
policies()tuple[Policy, ...]none, constant, linear, exponential, exponential-jitter, fibonacci.
named(policy: str)Policy | None
spec(backend, model, provider="")strspec("codex", "gpt-5.6-sol", "work") → "codex@work/gpt-5.6-sol".
reads(said: str)strThe canonical spelling, or "" for none.
all()list[Falls]Every step, in the order written.
tried(said)FallsThe step for a place (empty Falls where none).
chain(said)list[str][said, *to] where a rule is written against said, else [said]: a place only on somebody else's chain has none, and chains are never joined.
points(said, to: Sequence[str])FallsSets the places said falls back to, in order ([] none; a single string is one place). ValueError: not a place, itself, or a place named twice.
retrying(said, tries: int, policy: str, timeout: float)FallsSets extra tries (0 none), the wait policy, and the total limit in seconds (0 none). ValueError.
clear(said)boolRemoves the step.

Epics ​

Hmz().epics, or Epics(workspace=None). A run is named by its epic directory.

MethodReturnsBehaviour
under()PathThis workspace's epics directory.
all()list[Path]Every epic, oldest first.
read(epic: Path)Ran | NoneNone for a directory holding no run.
sessions(epic)list[Session]Every session, across every record of the epic.
opened(epic)dict[str, list[str]]Session ids per agent, by its name.
resumed(flow: str)Path | NoneThe epic --resume would pick up. flow: canonical ref or name as run.
picks_up(epic)boolWhether its journal has an entry, it is not going, and it is not foreign.
foreign(epic)strWhy an imported run cannot be picked up here (its workspace is not at that path, or lacks the commit its bundle recorded), or "".
state(epic, flow: str = "")dict[str, Any]A resumable flow's kept ctx.state: the run's own flow, or another by canonical ref.
traced(epic, *, output=None, start=None, end=None)tuple[Path, dict]Gathers the run's own sessions into a Chrome trace. Default output: the epic's traces/, named for the moment. start/end: any wording dateparser reads. Tracing.
trace(*, sessions=None, agents=None, output=None, start=None, end=None, profile=None, flow_profile=None, kept=None)dictThe same collector for any sessions. sessions=None: every session of the workspace; empty iterable: none. kept: directories of kept sessions to read (default: everywhere Humanize keeps them).
transcripts(epic)list[dict]What each session of the run said and did, read back out of its logs: per session that did anything, key (<cli>:<id>), agent and actions -- each category, name, at, start, seconds and args -- in order. Writes nothing.
timeline(epic)TimelineThe run as an Exomyth timeline: .document, and .span(id) for one span whole. Writes nothing.
bundled(epic, *, output, transcript=None)tuple[Path, dict]One .hmzepic of the whole run, credentials struck out. output (required): a file, or a directory to put it in. Returns the path and its manifest. Exporting a run.
imported(archive)PathReads a .hmzepic back in as an epic of the workspace it ran in, wherever that is. ValueError for anything else, an unsafe member, or an epic already here. Importing a run.

Host ​

python
class Host:
    def __init__(self, hmz: Hmz) -> None

A workspace's runs as every attached frontend shares them. Hmz().host() holds one in this process; a daemon holds one in its own. Frontends reach it through Link rather than calling it directly.

MemberReturnsBehaviour
attach(name, kind, heard, *, replay=True)strAttaches a frontend; returns its client id. kind: tui, web, cli or sdk. name "": login + @kind; duplicates get #2, #3. heard(message) is called on a thread of the host's. RuntimeError once closed.
detach(client)NoneLets one frontend go: its claims are released and its asides closed.
attachedintProperty: frontends attached.
idleboolProperty: nothing running or stopping, nobody attached, and no unread ended run.
closedboolProperty.
away_for(role)boolWhat afk last said of that role, else of every role.
printed(text)NoneSends one printed line to every frontend.
asked(client, said)dictCarries out one request; returns {"ok": …, "why"?: …}.
status()dictSee Daemon.status.
close()NoneCloses every run, tells every frontend gone, and waits a bounded time for runs to release what they made.

Daemons ​

python
class Daemons:
    def here(self, workspace: str | os.PathLike[str] | None = None) -> Daemon | None
    def all(self) -> list[Daemon]
    def host(self, workspace: str | os.PathLike[str] | None = None) -> Daemon
MethodSame asBehaviour
here(workspace=None)hmz.daemon.runningThe host holding that workspace's runs, or None (no daemon answers on this machine's socket, or it holds no host of that workspace).
all()hmz.daemon.daemonsEvery live workspace's host on this machine, oldest first.
host(workspace=None)hmz.daemon.hostThe host of the workspace, started where none is -- and this machine's daemon with it (10 s each to come up). OSError: an older Humanize's daemon is running, or none came up.

workspace=None is the current directory.

Daemon ​

python
@dataclass(frozen=True, slots=True)
class Daemon:
    at: Path            # this machine's daemon's directory (socket, daemon.json)
    workspace: str      # the project directory its host holds runs for
    pid: int            # the host process
    started: str        # UTC, ISO 8601
    protocol: int = 0   # the frontend protocol the daemon speaks; 0 = an older Humanize's
MemberReturnsBehaviour
aliveboolProperty: the process exists.
link(name="", kind="sdk", *, replay=True)LinkAttaches a frontend. OSError: nothing accepts the connection, or hello is refused or not answered within 10 s. protocol is not checked here (host() and hmz check it).
status()dictStatus keys; from these fields for a host that does not answer.
detach()intLets every frontend go; runs continue. Returns how many.
stop(*, seconds=20.0)boolAsks the host to close its runs and exit; waits up to seconds. Whether it has gone.
kill(*, seconds=20.0)boolSIGTERM to the host process, then SIGKILL; the daemon and other workspaces' hosts go on. Whether it has gone.
asked(said: dict)dictSends one control request; {} where no answer came.
python
class Link:
    client: str
    def told(self, message: dict[str, Any]) -> None
    def heard(self, listener: Callable[[dict[str, Any]], None]) -> None
    def __iter__(self) -> Iterator[dict[str, Any]]
    def asked(self, said: Mapping[str, Any], *, seconds: float | None = None) -> dict[str, Any]
    def start(self, flow: str | os.PathLike[str], task: str, *,
              agents: Mapping[str, Any] | None = None, envs: Mapping[str, Any] | None = None,
              params: Any = None, budget: Any = None, profile_flow: bool = False,
              profile_environment: bool = False, resume: bool | str | os.PathLike[str] = False) -> dict[str, Any]
    def say(self, text: str, *, to: str = "") -> dict[str, Any]
    def answer(self, question: str, text: str) -> dict[str, Any]
    def stop(self) -> dict[str, Any]
    def force(self) -> dict[str, Any]
    def afk(self, *, on: bool, role: str = "") -> dict[str, Any]
    def claim(self, role: str, *, take: bool = False) -> dict[str, Any]
    def release(self, role: str) -> dict[str, Any]
    def board(self, key: str, value: str) -> dict[str, Any]
    def aside(self, **said: Any) -> dict[str, Any]
    def close(self) -> None
    def __enter__(self) -> Self
    def __exit__(self, *exc) -> None      # close()

One frontend of a Host, in this process or over a daemon's socket; the same class either way. Obtained from Daemon.link, or hmz.daemon.linked(host, …) for a host in this process.

MemberBehaviour
clientThis frontend's client id; owner and client fields in messages use it.
told(message)Called by the transport to deliver a message. Not for callers.
heard(listener)Delivers every message, already-queued ones first, to listener on a thread of the link's own, in order. RuntimeError if a listener is already set.
__iter__Yields every message in order until gone or close(). RuntimeError if a listener is set.
asked(said, *, seconds=None)Sends one request and waits (seconds=None: indefinitely; ignored in process). Returns the reply (ok: true). Raises Refused with the reply's why, or TimeoutError("no answer to '<do>' in <s>s").
start(…)start request. agents/envs: specs as -a/-e after <role>=. params, budget: mappings or models (serialised). profile_flow, profile_environment: whether the run's flow, and the programs its agents start, are profiled. Reply carries run.
say, answer, stop, force, afk, claim, release, board, asideThe request of the same name.
close()Lets go of the host; runs continue.

Every method that sends a request goes through asked and raises Refused when refused, including after the host has gone (the reason is then the gone reason). Link has no helpers for the unaside, status, detach and quit requests: send them with asked({"do": …}). Transport differences (socket or in process) are in Daemon › Link.

python
from hmz.sdk import Daemons

with (Daemons().here() or Daemons().host()).link(name="ci", replay=False) as link:
    link.claim("reviewer")
    for said in link:
        if said["type"] == "pending":
            for asked in said["pending"]:
                if asked["owner"] == link.client:
                    link.answer(asked["question"], "looks good")

fakes ​

hmz.runtime.flowing.fakes, whole. __all__:

NameIs
run_fake(flow, task="", *, agents=None, envs=None, params=None, budget=None, outworlder=None, local=None, journal=None, resume=False, recorder=None)Runs a flow on fakes in memory.
FakeAgentDriver(harness=HarnessKind.CLAUDE, *, reply=None, model="fake", effort="", provider="", capabilities=None, cost=0.0, output_tokens=1, seconds=0.0, forks=None, names_late=False)A scripted agent driver. Also accepted by Hmz.run(agents=…), which then writes a real epic.
FakeSessionA session of a FakeAgentDriver.
FakeEnvDriver(files=None, *, workdir="/work", backend=EnvBackendKind.LOCAL, provider="", capabilities=None, cpu_count=8, memory=64 GiB, gpu_count=0, gpu_memory=0, run=None, refs=("HEAD", "main"), repo=True)An in-memory environment.
FakeOutworlder(reply=None, *, away=False)An outworlder answering from a script.
Answer, Command, Handler, ReplyType aliases for the scripts above.

Semantics: Flows › Testing a flow.

Returned types ​

Internal types returned by the classes above. Named tuples and frozen dataclasses; fields in declaration order.

Line ​

hmz.runtime.runner.Line (named tuple), from Hmz.read.

FieldTypeDefaultFrom
flowstr—-f
taskstr—task
agentstuple[AgentSpec, ...]()every -a, in order
envstuple[EnvSpec, ...]()every -e, in order
paramsdict[str, str]{}every -p but budget.*, values unparsed
budgetBudget | NoneNoneevery -p budget.<limit>=, parsed
profile_flowboolFalse--profile-flow
profile_environmentboolFalse--profile-environment
resumeboolFalse--resume
as_jsonboolFalse--json

AgentSpec, EnvSpec ​

hmz.runtime.flowing.specs, frozen dataclasses. str() writes each back as its flag takes it.

TypeFields
AgentSpecrole: str, harness: HarnessKind (ACP for an ACP CLI), provider: str ("" = as local), model: str, effort: str ("" = auto), cli: str
EnvSpecrole: str, backend: EnvBackendKind, provider: str (a saved runtime's name, an ssh host nobody saved in its brackets, "[me@box:22]", or "" for this machine), workdir: PurePosixPath (~/… relative to home)

Flow types ​

TypeFields
Offerwhose: str (a flowverse, local or user), name: str (what -f takes: aot, alice/kernel, @theirs/review, @local/x), about: str
Declarationname, ref, description: str | None, hidden: bool, resumable: bool, agents: tuple[AgentRole, ...], envs: tuple[EnvRole, ...], params: type[FlowParams]; methods agent(name), env(name) → role or None
AgentRolename, declared: type, required: bool, auto: bool (runtime-filled), harness: HarnessKind | None, capabilities: frozenset[type], permission, skills: tuple[str, ...], grant
EnvRolename, declared: type, required, auto, capabilities, cpu_count: int, memory: int, gpu_count: int, gpu_memory: int, image: str, grant, resources: bool
LiveCallref, name, depth: int (1 = the run's flow), since: float (monotonic), id: int (journal id, 0 = none), parent: LiveCall | None, task: str, resumable: bool
Flowversename, url ("" for local, user), at: Path, fetched: bool, fixed: bool (official, local, user)

Flowverse types ​

hmz.runtime.flowing.index; all but Skipped are also exported from hmz.runtime.flowing.

TypeFields
Index (named tuple)verse: str, releases: tuple[Release, ...] (by index name, newest first), skipped: tuple[Skipped, ...]; methods flows() (index names, aot and alice/kernel, sorted), versions(flow) (newest first), release(flow, version) → Release | None, newest(flow, spec="") → the newest in range that is not a prerelease, else the newest prerelease, else None
Release (pydantic, frozen)name, version, description, repo, ref, commit, subdir, license, dependencies: dict[str, str], owner (the <user> it is listed under, "" bare); properties listed (its index name), owned (its repository's GitHub owner, or ""), semver (a semver.Version), url (what git fetches)
Skipped (named tuple)at: Path (the manifest, or a <user> directory), why: str
Installed (pydantic, frozen)verse, name, version, commit, repo, ref, subdir, dependencies, owner; properties listed (its index name), called (the name it is offered under), at: Path (its directory)
Update (named tuple)installed: Installed, version: str (the newest after it)

Account types ​

TypeFields
Providercli, name, way: str = "env", env: Mapping[str, str], args: tuple[str, ...], made: str; property at: Path; methods held(), command(argv), swaps()
Wayname, about, argv: tuple[str, ...] (sign-in command), asks: tuple[Asked, ...], sets: tuple[tuple[str, str], ...], args: tuple[str, ...], stdin: str
Modelname, efforts: tuple[str, ...] (hardest first), swarms: bool = False
Fallsspec, to: tuple[str, ...] (() = nowhere), tries: int = 0, policy: str = "exponential-jitter", timeout: float = 0.0; method says()
Policyname, about

Environment types ​

TypeFields
SSHRuntimename, host, user, port: int = 0, identity_file, proxy_jump, options: Mapping[str, str], alias, config, workdir, made: str = "typed" (typed/imported); property at; methods destination(), login(), settings(), target() (coganchor target), held(); backend == "ssh"
DockerRuntimename, endpoint: str = "local", tls_dir, container, exec_user, exec_env: tuple[str, ...], exec_wrapper: tuple[str, ...], image, runtime, run_args: tuple[str, ...], name_prefix, cpus: float, memory: int (bytes), gpus: tuple[str, ...], gpu_memory: int, max_containers: int (0 = no limit), workdir, made; property at; methods daemon() → Endpoint (Machines), exec_options(), held(); backend == "docker"
SSHHostalias, host, user, port: int, identity_files: tuple[str, ...], proxy_jump
Checkedreached: bool, said: str, home: str, cpus: float, memory: int, gpus: tuple[str, ...], gpu_memory: int, runtimes: tuple[str, ...], version: str, short: tuple[str, ...] (what it is saved to hand out and has not got)

Epic types ​

hmz.runtime.epic, named tuples. Values as the epic record wrote them.

TypeFields
Ranat: Path, flow, task, workspace, began, ended ("" while running or abandoned), how (done, failed, stopped, or ""), agents: tuple[Drove, ...], sessions: tuple[Session, ...], called: tuple[Called, ...], resumable: bool, ref, envs: tuple[str, ...] (as -e spells them, a run's kept in an older spelling included), params: dict, budget: dict | None, picked_up: str (epic name or ""), profile_flow: bool, profile_environment: bool (whether its flow, and the programs its agents started, were profiled); property name
Droveagent (the role), backend, model, effort ("" = auto), provider ("" = as local), name (what the agent filling it is called; "" in an epic written before agents had names); property spec (-a spelling after <role>=)
Calledflow, task, record (file in the epic), began, ended, how, calls: tuple[Called, ...]
Sessionagent, backend, provider (local = as local), ident (backend's id), name, at, flow, parent (forked-from id or ""), record, where (kept-session path), harness (local, env, the <backend>:<name> of a runtime a harness setting named, or "" for work on this machine)

Released under the Apache-2.0 licence.