Skip to content

The agent surface

An agent that manages a fleet works through queries. Every answer is data that builtins.toJSON prints, so a tool, a script or a model reads it the same way.

r.agent is the schema, the errors, the invariant check and the counts, JSON-safe:

result
{
check = {
incomplete = [ ];
ok = true;
violations = [ ];
};
counts = {
aspects = 3;
edges = 4;
kinds = 2;
scopes = 4;
};
errors = [ ];
schema = {
aspects = {
desktop = {
activeAt = 1;
cycle = false;
files = [
"modules/fleet.nix"
];
keys = [ ];
};
metrics = {
activeAt = 3;
cycle = false;
files = [
"modules/agent/metrics.nix"
];
keys = [
"services"
];
};
postgres = {
activeAt = 1;
cycle = false;
files = [
"modules/fleet.nix"
];
keys = [
"services"
];
};
};
invariants = [ ];
kinds = {
fleet = {
fields = { };
instances = 1;
scopes = 1;
sinks = {
out = {
conditional = false;
feeds = [ ];
of = null;
out = false;
reduce = "merge";
};
};
spawns = [
"host"
];
};
host = {
fields = {
addr = {
type = "str";
};
form = {
type = "enum";
};
};
instances = 3;
scopes = 3;
sinks = {
services = {
conditional = false;
feeds = [ ];
of = null;
out = false;
reduce = "list";
};
};
spawns = [ ];
};
};
queries = [
"errors"
"graph"
"scopes"
"active"
"reduced"
"undefined"
"declaredIn"
"facts"
"check"
"schema"
"flake"
];
};
undefined = [ ];
}

r.explain aspect id depth traces at at one scope: the value of each node of the predicate, what the aspect gives there, and its files. Past the depth, kids = "cut".

result
{
active = false;
aspect = "postgres";
at = {
kids = [
{
instance = "host:db";
op = "instance";
value = false;
}
];
op = "any";
value = false;
};
files = [
"modules/fleet.nix"
];
gives = [ ];
scope = "fleet:main/host:web";
}

An unknown aspect or scope is an error record with near: the names it was probably meant to be.

yen.labels."<path part>" = { trust = n; } labels the content of files whose path contains that part. An aspect declared in several files takes the lowest trust of them.

modules/labels.nix
# Content gets the trust of the files that declare it: files under agent/ are written by agents.
{ ... }:
{
yen.labels."agent/" = {
trust = 1;
};
}
modules/agent/metrics.nix
# Written by an agent.
{ yen, ... }:
{
yen.aspects.metrics = {
at = yen.kinds.host;
services = "prometheus-node-exporter";
};
}

r.labels gives each labelled aspect. r.floor 3 lists every routed element of an aspect below trust 3, with its file: what a reviewer reads first.

result
[
{
aspect = "metrics";
file = "modules/agent/metrics.nix";
to = "fleet:main/host:db";
trust = 1;
}
{
aspect = "metrics";
file = "modules/agent/metrics.nix";
to = "fleet:main/host:thinkpad";
trust = 1;
}
{
aspect = "metrics";
file = "modules/agent/metrics.nix";
to = "fleet:main/host:web";
trust = 1;
}
]
QueryAnswer
agentschema, errors, check and counts
schemakinds, aspects (keys, files, how many scopes), invariants
context id { maxEdges; maxAspects; }one scope and its neighborhood, with truncated
explain aspect id deptha trace of at at a scope
declaredIn paththe files that answer a declaration path
labels, floor ntrust per aspect; elements below a trust
impact id { hops; sinks; max; }what a scope’s elements reach, by depth
Contribute Community Sponsor