Tenant — one platform cycle under roles, quota and audit¶
agentdescent tenant puts the existing WorkspaceRegistry around one platform
cycle: the principal must have run:write in the workspace, the cycle reserves
the stated tokens/cost, and the usage is committed through the audited quota
path. It composes WorkspaceRegistry + Principal/Workspace/Quota +
TenantPlatform + the platform spec.
Quickstart¶
agentdescent tenant init --out tenant.json --demo
agentdescent tenant plan --spec tenant.json
agentdescent tenant run --spec tenant.json --json --out report.json
The demo runs offline on the platform demo step and commits its reserved tokens/cost.
Spec¶
{
"platform": {
"runs_db": "tenant-runs.sqlite3",
"platform": {"tenant": "t1", "workspace": "default",
"max_generations": 3},
"step": "mypkg.steps:step"
},
"tenant": "t1",
"workspace": "default",
"principal": "operator",
"roles": ["operator"],
"quota": {"max_tokens": 10000, "max_cost": 100.0, "max_concurrent": 2},
"tokens": 100,
"cost": 1.0
}
- The nested
platformobject is exactly theagentdescent platformspec. tenant/workspacemust matchplatform.platform; the principal belongs to that tenant and getsroleson that workspace.rolesis a comma-separated list or JSON array;operatoris the minimum for a run,vieweris refused before the platform starts.tokens/costare the reservation (the prepaid charge);usage_ofis an optionalmodule:attributecallable returning actual(tokens, cost).quotais aQuotaobject:max_tokens,max_cost,max_concurrent(zero means unlimited).
plan validates the nested platform refs and checks run:write without
creating the SQLite DB. run exits 1 only for an incomplete cycle; a denied
role or exhausted quota is an input error (exit 2). On MCP, refs use
AGENTDESCENT_SURFACE_ALLOW and runs_db/out writes use
AGENTDESCENT_SURFACE_WRITE_DIRS.
Roles are asserted by the spec, not authenticated: the viewer refusal catches a
misconfigured spec, not a caller (including an MCP model) that writes
"roles": ["owner"]. The registry is in-memory and created fresh for each
invocation, so quota does not accumulate across runs and its audit trail is not
persisted; production tenancy needs the persistent adapter described in
docs/governance.md. tokens and cost are required explicitly, so a typo
cannot turn a metered cycle into a free one.