> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Workload identity

> A named, organization-scoped identity your agent runs as — so attribution and policy can tell human-driven work from autonomous work.

hiloop has three kinds of principal: a **user** (a human identity), a **service account** (a machine
credential not bound to a user), and a **workload** — a named, organization-scoped identity that a run is
*launched as*.

<Note>
  Workload identity applies to **runs** today: `hiloop run --as workload/<name>` is the only verb that
  takes `--as`. `hiloop sandbox create` has no workload declaration, so a sandbox does not yet carry an
  ambient workload identity, and the sandbox-side pieces below describe the shape that lane will take
  rather than behavior you can use now.
</Note>

Get the vocabulary straight first, because "agent" is an overloaded word: in these docs an **agent**
is always your program — the LLM harness that calls models, runs tools, and edits files. A
**workload** is the identity it assumes. *Your agent runs **as** a workload identity.* The agent is
the subject; the workload is the security identity the platform attributes, authorizes, and bounds.

## Why a third kind exists

A person running code directly and an autonomous agent operating unattended in the same organization are
different risks. The unattended workload is the exfiltration case a lockdown exists for, not the
human at the keyboard. To treat them differently, the platform needs to know *who is driving* the
work, and a service account cannot say: it names a credential, not what that credential is
currently doing.

A workload identity closes that gap. It gives autonomous execution:

* **A name of its own.** Work shows up attributed to `codex-runner`, not to the API key of whoever
  happened to start it.
* **A policy attach point.** Because human-launched and workload-launched work carries different
  identities, policy can treat them differently: locking unattended workloads down while humans
  keep a laxer baseline (see [network egress](/sandboxes/network-egress) for what sandboxes
  enforce today).
* **A provenance trail.** Every workload launch records the principal that launched it, so an action
  reads as a delegation: *executing as workload `codex-runner`, on behalf of the user who launched
  it.*

A workload is not a user: it has no login, no console session, and no organization membership. It is a
registered name with an owner trail and a launch ACL.

## Register a workload

Registration is always explicit — launching as an unregistered name is an error, never an implicit
registration. Any member of the organization can register one:

```sh theme={null}
hiloop workloads create codex-runner --description "Nightly refactor bot"
```

Names are unique per organization: lowercase letters, digits, `.`, `_`, and `-`, starting and ending with
a letter or digit, at most 100 characters.

List and inspect the registry:

```sh theme={null}
$ hiloop workloads list
NAME            ID                                    LAUNCH          CREATED
codex-runner    5f8b9c1e-3d5a-4e2b-9c7d-1a2b3c4d5e6f  members         2d
report-fetcher  9a1c2d3e-4f5a-6b7c-8d9e-0a1b2c3d4e5f  restricted (2)  1d

$ hiloop workloads show codex-runner
NAME         codex-runner
ID           5f8b9c1e-3d5a-4e2b-9c7d-1a2b3c4d5e6f
DESCRIPTION  Nightly refactor bot
LAUNCH       members
CREATED BY   0d9e8f7a-6b5c-4d3e-2f1a-0b9c8d7e6f5a
CREATED      2026-07-05T00:00:00Z
```

`LAUNCH` is the workload's launch ACL: `members` (any member of the organization may launch as it — the default)
or `restricted (N)` with the number of allowed launchers. Pass `--output json` for the full record.

## Declare it at launch

The executing identity is **declared, never inferred**. Pass `--as workload/<name>` when you start a
run; without `--as`, the work runs as your own identity:

```sh theme={null}
# The coding agent runs AS the codex-runner workload
hiloop run --as workload/codex-runner -- codex "fix the failing test"

# No --as: runs as you, a user rather than a workload
hiloop run -- python train.py
```

The declaration is checked before anything starts:

* The name must be **registered** — an unknown workload name is rejected, not auto-created.
* You must hold **launch rights** on it (see [the launch ACL](#the-launch-acl)).

Once declared, the identity is fixed for the lifetime of the run. It is recorded on the run's
record and cannot be changed after the fact.

## The launch ACL

Each workload carries an ACL saying who may launch as it. A new workload starts open to every member of the organization
member. To restrict launching to named principals — or open it back up — use `allow-launch`
(requires an owner or admin in the organization). A launcher is either a **user** (an organization member, named
by user id) or a **service account** (a machine credential, named by its key id — how you authorize
a CI pipeline to launch a restricted workload):

```sh theme={null}
# Only this user and this service-account key may launch as codex-runner
hiloop workloads allow-launch codex-runner \
  --user 7c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f \
  --service-account 3e4f5a6b-7c8d-9e0f-1a2b-3c4d5e6f7a8b

# Back to any organization member
hiloop workloads allow-launch codex-runner --all-members
```

The `--user`/`--service-account` flags replace the previous list together. A restricted workload is
launchable only by the principals on its list: a listed user's session or user-bound key, or a
listed service-account key presented directly. Anyone else's `--as workload/<name>` is rejected —
including service-account credentials that are not on the list; machine launchers are never implied,
only named. A service-account entry must name a live, non-revoked service-account key in your
organization.

## Delete a workload

Deleting a registration requires an owner or admin in the organization, and asks for confirmation unless
you pass `--yes`:

```sh theme={null}
hiloop workloads delete codex-runner
```

Deletion is idempotent: deleting a name that is not registered — including a repeat of a delete
that already completed — succeeds, so a retried delete converges instead of erroring.

Two honest edges:

* A workload with work **still running under its identity** is a conflict: let it finish, or stop
  it, then delete.
* Past runs keep the workload's raw id in their attribution, but once the name is gone that id no
  longer resolves to a name. Delete freely to clean up a typo'd registration; prefer keeping
  workloads that own meaningful history.

## Attribution and delegation

A workload launch records two identities, not one:

* **As what identity is this executing** — the workload. The run is workload-classed.
* **Under whose authority** — the principal that launched it, recorded on that credential. This is
  standard delegation ("on behalf of"): the human delegates to the workload, and the record keeps
  both ends.

The executing identity flows through observability:

* A workload-classed run renders the workload's **registered name** in `PRINCIPAL` columns
  (`hiloop runs list`, `hiloop runs show`) — attribution names the identity
  the run executes as, not the credential that launched it. The record keeps both: the run's
  `executing_principal`/`executing_kind` name the workload, `created_by` stays the launcher.
* `hiloop runs list --principal codex-runner` filters to a workload's runs (a workload name filters
  the runs executing as it; a key or user name filters the runs it created).
* The event schema reserves executing-identity attributes for future runtime-native `egress`
  decision producers. The current fixed network floor does not emit destination decisions.

## Short-lived cloud credentials

A workload is designed to reach your cloud accounts without any static key entering the sandbox.
Each deployment serves an OIDC issuer for workload identity; a process running as a workload mints
a short-lived, audience-bound JWT on demand and exchanges it directly with AWS, Google Cloud, or
Microsoft Entra through their native workload-identity federation. No long-lived cloud credential
is stored anywhere, no refresher daemon runs in the guest, and no default token file is created.

Registering federation works today. **Minting a token from inside a sandbox does not**: it depends
on the sandbox carrying an ambient workload identity, which it cannot yet be launched with. Register
the trust now if you like, but do not build a flow that depends on the in-sandbox exchange yet.

Federation is registered per workload and per cloud. The provider audience is derived server-side
from the registered descriptor, so a workload can request tokens only for audiences an owner or
admin registered:

```sh theme={null}
# Trust codex-runner to assume exactly one AWS role
hiloop workloads federation add codex-runner \
  --cloud aws \
  --role-arn arn:aws:iam::123456789012:role/agent-readonly \
  --idempotency-key reg-codex-aws-1

# The registration list is the workload's token-audience allowlist
hiloop workloads federation list codex-runner

# Print the exact cloud-side trust configuration for one registration —
# read-only, issuer- and subject-pinned to this organization and workload
hiloop workloads federation setup codex-runner <federation-id>
```

Google Cloud registrations take the project id, project number, and workload identity pool and
provider ids (with optional service-account impersonation); Microsoft Entra registrations take the
application and organization ids. Removing a
registration revokes the audience on the hiloop side; the trust you created in the cloud account is
yours to remove separately.

Inside a sandbox that carries an ambient identity, `hiloop workload-identity` is what wires the
cloud SDKs to it:

* `token` mints one short-lived federation JWT and writes only the token to stdout.
* `aws-credentials` emits AWS `credential_process` JSON after an in-process web-identity exchange.
* `gcp-credential-source` emits Google Cloud's executable-sourced subject-token envelope.
* `azure-token-file` refreshes the Microsoft Entra SDK fallback token file on boot-local tmpfs.
* `setup` prints the exact SDK wiring for the workload's registered federation descriptors.

Because the cloud-side trust policy pins the issuer and the workload's subject, a cloud API call
made this way is attributable to the workload on both sides of the boundary: in your cloud audit
log and in the hiloop run record.

## Related pages

* [Network egress](/sandboxes/network-egress) — the current fixed floor and destination-filtering gap.
* [Glossary](/concepts/glossary#workload-identity) — workload identity next to the rest of the vocabulary.
* [Event model](/observability/event-model#egress-network-policy-decisions) — the `egress` signal's identity attributes.
* [Security model](/deployment/security-model) — where network egress enforcement sits in the layered defense.
