lazy documentationv0.94Contents

Agents, the proxy and credentials

sequenceDiagram
  participant A as Agent in task container
  participant P as Proxy
  participant C as Credential store
  participant M as Model provider
  A->>P: Request with task placeholder
  P->>C: Resolve real credential
  C-->>P: Credential
  P->>M: Forward request
  M-->>P: Response and usage headers
  P-->>A: Response
An agent sends a placeholder token to the proxy, which resolves a credential and forwards the model request

Lazy runs four agent harnesses: Claude Code, Codex, Cursor and Pi. A task picks one through an agent profile. All four are launched the same way, in a task container, and all four reach their model through the same proxy.

What the proxy does

The proxy is a process the daemon runs on the host, always on, listening on loopback by default ([proxy] bind). Every agent is handed the proxy's address, never the provider's, so nothing an agent sends goes to a model without passing through it. For each request the proxy:

  1. identifies the caller from its placeholder token;
  2. picks the upstream the caller's profile points at (a provider, or an endpoint such as a local Ollama);
  3. swaps in the real credential;
  4. records the call (tokens, timing, which task) in a bounded audit log, and reads the provider's usage-limit headers.

On a single-person install, the project root's lazy.toml can state the local listener explicitly. Lazy Teams assigns the listener address for its projects.

[proxy]
bind = "127.0.0.1"

This confines the proxy listener to the local machine.

Placeholder tokens

At launch the daemon mints a random placeholder per task and role, and puts it in the environment variable the harness would normally read its credential from, shaped like the real one. The proxy looks the placeholder up to learn the task and the agent profile; it does not trust anything the agent says about itself. The placeholder cannot authenticate to the provider directly, but treat it as a live token for this machine's proxy until it is revoked when the task ends. Where Docker lets lazy tell containers apart (native Linux Docker) it is also pinned to its own container; on Docker Desktop, rootless or remote Docker it is not. Full mechanics: Just-in-time credential injection.

Per harness

Each harness is pointed at the proxy in the way it supports:

The credential store

Real credentials live with the daemon, not in any project file. lazy auth set stores one in the operating system's keychain or libsecret store, or in a file store when neither exists. The proxy resolves it on each request, outside the task containers. When a change takes effect is covered in Credentials.

How usage limits are read

The proxy keeps only response headers that report rate limits, for example the 5-hour and 7-day windows of a Claude subscription, and the equivalents some other providers send. Anything else in a response's headers is dropped, and a value that looks like a secret is refused. The latest reading per credential is held by the daemon and survives a restart. lazy stats limits and lazy stats budget show it, and [usage_pause] can hold new turns past a threshold. See Token budgets. A harness whose provider sends no such headers shows no reading.

More: The daemon, the task container and the proxy.

When a model request fails

Every error the proxy returns says which party failed:

Providers close idle connections, and a request that crosses that close is reset before any answer. The proxy sends that request once more, straight away, on a fresh connection. This only happens when nothing was received yet and the request body can be sent again. The agent sees no error.

To see whether a provider is having a bad hour, check provider health. It lists each provider over the last hour: how many requests, failures by kind (reset, timeout, connect, 5xx, 529, 429), and the latest failure. lazy's own refusals are not counted. You can find it in: