opencrow-workloadd is the workload policy and ledger sidecar for OpenCrow.
It keeps the runtime split explicit:
- OpenCrow executes workload triggers and reports lifecycle truth.
opencrow-workloaddowns policy, dedupe, source state, capabilities, and audit.- n8n owns source connectors and source-specific parsing.
graph LR
n8n["n8n\nconnectors + parsers"] -->|events / dispatch| Workloadd[("opencrow-workloadd\npolicy + ledger")]
Workloadd -->|trigger.pipe| OpenCrow["OpenCrow patched\nexecutor"]
OpenCrow -->|lifecycle| Workloadd
OpenCrow -->|runs| Agent["agent / pi"]
Agent -->|context hooks| n8n
opencrow-workloadd audits managed workloads that enter through the n8n/source
adapter flow. It is not a sandbox audit system for every action an interactive
agent session can take.
The ledger records:
- why a workload was assigned: source event, matched rule, and dedupe claim
- when it was assigned and delivered: workload rows and trigger outbox
- execution lifecycle reported by OpenCrow: running, completed, failed, aborted, preempted, or dropped
- scoped context permissions granted to the workload
- context capability authorization and use counts
- terminal cleanup of workload-bound capabilities
Out of scope:
- arbitrary interactive agent actions outside the managed workload flow
- direct shell, network, or secret access not mediated by context or mutation hooks
- full transcript or final reply content, unless linked later through OpenCrow artifacts or hashes
Operators can audit current state from the SQLite ledger. A read-only audit HTTP API may be added later for dashboards and tooling, but the agent itself should not read the database directly.
packages.<system>.defaultpackages.<system>.opencrow-workloaddnixosModules.defaultnixosModules.opencrow-workloaddoverlays.default
{
services.opencrow-workloadd = {
enable = true;
listenAddr = "0.0.0.0:8766";
dbPath = "/var/lib/opencrow/opencrow-workloadd.sqlite";
tokenFile = "/run/credentials/opencrow.service/n8n-hooks-mutation-token";
triggerPipe = "/var/lib/opencrow/sessions/trigger.pipe";
lifecycleSocket = "/run/opencrow-workloadd/lifecycle.sock";
after = [ "opencrow.service" ];
requires = [ "opencrow.service" ];
};
}go test ./...
nix build .#opencrow-workloadd --no-link