PROJECT / GOVERNED HARNESS

Loro

Loro is the harness I built for work where being able to demonstrate what happened matters as much as the work happening. Identity, permission decisions, approval records, sandboxing, and delivered audit are structural rather than features layered on afterwards.

Project

What it is

Loro is a Python command line agent harness aimed at enterprise coding, governed data work, and productivity tasks. The name is Spanish for parrot: a bird that listens, learns, and helps information move between groups.

What makes it different from the general category is where it starts. Identity, permission decisions, approvals, sandboxing, and audit are the foundation, and capability is added inside them. Most harnesses do the reverse, which produces systems that work well right up until someone asks who authorized a particular action.

Why I started with the controls

I built the other way round first, and it did not work.

The natural path is to build capability and add controls later. You get something useful quickly, and the controls become conditionals inside tool implementations. Ask what the agent may do and the answer requires reading code. Ask what it did and the answer requires reconstructing from logs that were never designed for the question.

The point where this became untenable for me was not a security incident. It was a conversation. Someone reasonably asked which systems an agent had touched during a task, and I could not answer without spending a day, and my answer would have been an inference rather than a record. That is a bad position, and no amount of additional capability improves it.

Retrofitting was worse than starting over. Authority added afterwards ends up distributed across every tool, with gaps wherever a tool was written before the model existed. So Loro starts with an explicit identity on every run, a policy decision point every tool action passes through, an approval record bound to the identity that gave it, and an audit stream that is delivered rather than merely written.

The questions a harness should be able to answer

Who was this agent acting for. What was it permitted to do. What did it actually do. Who approved the parts needing approval. Can that be demonstrated six months later. If those require investigation rather than a lookup, the governance is decorative.

Identity comes first

Loro establishes an identity context from configuration and environment, with required fields that can be managed centrally, and propagates it into audit records and session state.

This addresses the structural weakness I see in most agent deployments. When an agent runs as itself with its own broad credentials, every action is attributed to the agent. Two different questions collapse into one: whether the agent was allowed to do something, and whether the person it was acting for was allowed. An agent then becomes a way to reach things the requester could not reach directly.

That is a governance hole no prompt discipline closes, and it is invisible until someone looks. Carrying a real principal through the run means permission checks and audit records both refer to a person, which also makes the trail readable by people outside the engineering team.

Policy over normalized resources

Loro normalizes what an agent can act on into resource kinds: filesystem, shell, Git, memory, catalog, provider, MCP, and session messages. Policy is expressed against those rather than against individual tools.

Normalization is what makes policy complete. If every filesystem action from any tool resolves to a filesystem resource with an action and a path, one rule covers all of them. Without it, each tool carries its own idea of what a write is, and every new tool silently introduces a gap.

There is also a command that explains why a specific decision was made, which is a small feature with an outsized effect. Policy that cannot be interrogated becomes policy nobody trusts, and the standard response to distrust is widening permissions until the friction stops. Being able to ask why keeps narrow policy workable rather than aspirational.

Approvals that survive replay

Approvals are identity-bound records with once, session, and deny options, plus replay protection.

The replay part is the detail that took me a while to get right. A naive approval asks a person to confirm an action and then proceeds. If the same approval can be reused for a subsequent different action, the confirmation was theater. Binding an approval to the specific proposed action, and to the identity that granted it, means the approval covers what was actually shown.

The related discipline is what gets displayed. A prompt asking whether to proceed, without the exact action, trains people to approve reflexively, and after twenty confirmations nobody is reading. Gating on irreversibility rather than on everything is not a shortcut, it is what keeps the remaining gates effective.

Subprocess profiles

Command execution runs through named subprocess profiles with minimized environments, bounded runtime and output, and optional sandbox enforcement.

Each element addresses a specific failure I hit. Minimized environments stop credentials in environment variables from being visible to every command, which is a quiet and very common exposure. Bounded runtime stops a hung process holding a task open. Bounded output stops a command that prints a large file from filling the context and evicting the task, which produces incoherent behavior that looks like a model problem. Sandbox enforcement bounds what the process can reach regardless of what it decides to do.

Together these are the adversarial test made concrete. If the model behaved adversarially, what could it actually do? With a narrow profile, a minimized environment, and enforcement underneath, the answer is bounded by construction rather than by instruction.

Local memory and governed shared memory

Loro separates local memory from shared memory, and the separation carries the argument.

Local memory is what one agent knows in one workspace. Shared memory is knowledge other agents and people will treat as true, and Loro backs it with Postgres and Apache Iceberg adapters. Shared writes are explicit-only and draft-gated rather than automatic.

That restriction is deliberate friction. An agent writing freely into shared state is publishing, and its errors propagate rather than staying local. Requiring a staged, reviewed write means shared knowledge accumulates on purpose. Teams that route around it lose the property that made it safe.

The Iceberg path also means agent memory can live in the same governed lakehouse as everything else, with the same catalog, the same access control, and the same snapshot history. Loro includes a read-only Polaris client so an agent discovers what tables exist through the catalog rather than from a hardcoded list that drifts.

A safety scanner checks for obvious secrets before memory and artifact writes. That addresses a failure that is easy to overlook and hard to undo: an agent reads a configuration file and writes what it learned into a shared store, having just moved a credential somewhere it was not before.

Audit is a delivery problem

Loro treats audit as versioned records delivered over files or HTTP, with bounded buffering, retries, diagnostics, an explicit flush, and verification commands.

Framing this as delivery rather than logging is the correction I most want to pass on. Logs are written locally, lost when the machine is, ignored when nobody aggregates them, and truncated when a process exits unexpectedly. None of those failures announce themselves.

An audit pipeline that stopped working three weeks ago is worse than none at all, because it produces confidence without coverage. That is why verification and diagnostics are part of the feature rather than an operational extra. Being able to check that delivery is healthy is the difference between a record and an assumption.

Artifacts with provenance

Loro generates documents, presentations, and spreadsheets, and attaches provenance sidecars bound by checksum, with a verification command.

This closes a loop most agentic systems leave open. Traces record what an agent did. Provenance connects what it did to the artifact that resulted, which is the direction the question actually gets asked from. A document produced by an agent gets emailed, filed, and cited, and six months later someone holding it wants to know where it came from. A checksum-bound record turns that into a lookup rather than a recollection.

Standards, adopted carefully

Loro implements the portable formats I care about, and it implements them conservatively.

Open Agent Profile support uses fail-closed narrowing, so a profile can only reduce capability. Profile state is treated as untrusted. Proposals are digest-bound. Writeback is restricted to an atomic state section. Every one of those constraints exists because a profile is a file, files can be edited, and a harness that lets a profile grant capability has moved its authority model into something anyone with write access can change.

Agent Skills support includes digest tracking, progressive loading, and reviewed installs. The review step matters: a skill is instructions an agent will follow, so installing one without review is closer to running code than to reading documentation.

Agentic Graph documents are validated and planned read-only over explicitly exported tools, and run with human gates held for an explicit decision. MCP connections work over stdio and streamable HTTP with deny-by-default handling of extensions, and Loro can act as an MCP server in a least-privilege mode with a read-only export ceiling.

The pattern across all four is the same: adopt the portable format, and do not let adopting it become a route around the authority model.

Gateways widen the perimeter

Loro supports signed, identity-mapped gateways to several chat platforms plus a generic one, and there is an optional local web interface. Both make an agent reachable from where people already work, and both change the security question enough to deserve saying out loud.

A terminal agent has an implicit authority model: whoever is at the keyboard is the user, and their shell permissions bound what is possible. A gateway removes that. Requests arrive from a platform, possibly from people with no account on the machine, through a channel that may include people the agent was never intended to serve.

Three properties matter, and the feature name states all three. Requests are signed, so the harness can verify a message came from the platform rather than from anyone who found the endpoint. They areidentity-mapped, so a platform user resolves to a real principal with real permissions rather than to a shared account. And the resulting run carries that identity into policy decisions and audit records.

The failure without these is worth naming because it is common and quiet. A chat-connected agent with a single service identity gives every member of a channel the union of that identity's permissions. Someone invites a contractor to the channel and has, without noticing, granted them whatever the agent can reach. Nothing misbehaved. The perimeter moved and nobody adjusted the authority model.

The web interface follows the same reasoning applied to different mistakes. Loopback binding by default, a fresh token per launch, append-only conversations, profile revision pinning, and rendering that never evaluates raw HTML from model output are five specific defenses: do not expose a local service to the network, do not leave a long-lived session open, do not let history be rewritten, do not let a profile change underneath a running conversation, and do not let model output execute in the page displaying it.

Who this is for

  • Regulated or reviewed environments. Where demonstrating authority and reconstructing actions is a requirement.
  • Agents touching governed data. Where lakehouse access through a catalog is the intended path rather than a tool someone wrote.
  • Work with real consequences. Where approval gates and reversibility matter more than autonomy.
  • Organizations with existing identity infrastructure. Where propagating a real principal is achievable.

It is not for a solo developer wanting a fast coding assistant. The governance machinery is overhead with no corresponding benefit there, and I would point that person at MagAgent instead. The mismatch is the failure, not the category.

Limits and honest caveats

  • Governance has setup cost. Identity, approvals, audit, sandbox, and memory each need configuring. The setup wizards reduce it and do not remove it.
  • Read the project status document. Loro maintains a deliberately limited stable core with a larger set of surfaces at varying stages. Do not assume uniform maturity.
  • Shared memory writes are awkward on purpose. Draft gating is friction by design.
  • Audit needs a destination and monitoring. Configuring delivery and never checking it produces false confidence.
  • Sandbox enforcement varies by platform. Verify what is actually active rather than what is configured.
  • Narrow policy needs maintenance. Policy that blocks legitimate work creates pressure to widen it. Reviewing denials periodically is how narrow policy stays narrow.

What it is not

Loro is not a broker. It runs agents under governance. Choosing between several installed harnesses is a different job, which is what Merced AI does.

Loro is not lightweight, and it is not trying to be. The machinery is the point.

Loro is not a substitute for organizational policy. It provides mechanisms for expressing and enforcing authority. Deciding what the authority should be is a human decision, and a harness with excellent controls configured permissively is not governed.

Where to learn more

Primary sources first. Repositories and specifications move faster than any summary, so treat the links below as the authority and this page as orientation.