# Agent observability

Observability for an agent is the ability to answer, later and without guessing, why it did that. It needs more than application logs, because the interesting question is rarely 'did the code run' — it is which rule applied, what the agent was working from, what it decided, and what the outside world said in reply.

- **Status:** Reference
- **Audience:** both, developer
- **In the app:** #/activity, #/autonomy-audit
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/technology/agent-observability/

## Four questions a record has to survive

1. **Why did it reply that way?** The material the answer was grounded in, and the instruction set that shaped it.
2. **Why did it not reply at all?** The rule that held it, which is a decision and needs recording as one.
3. **Did the action actually happen?** The provider's own acknowledgement, kept with the record rather than in a log.
4. **Who released it?** The person, the moment, and what they changed before approving.

Ordinary application logging answers none of those well. It is optimised for the minutes after a crash: high volume, short retention, sampled, and rotated away long before the customer complains. What an agent needs is the opposite shape — a small number of durable records attached to the objects they describe.

## Does Connect use agent observability?

**Used.** `audit.py` and `audit_api.py` hold the accountability trail: what was decided, by what, under which rule, and what happened — **including refusals**, on the principle that a refusal is a decision and a trail with only successes cannot explain a silence. The Decision Log renders it, and the activity view sits beside it for both audiences over one implementation.

Around that sit the records that make a specific case reconstructable: the canonical thread and its messages, the send evidence on each outbound, the call transcript and summary on the phone side, the cross-channel timeline on the relationship, and the memory tiers as they stand. **Needs You** carries the live half — decisions waiting, and operational problems such as voice line health, each entry draining when its cause clears rather than when somebody dismisses it.

Health checking is deliberately one endpoint: **`/api/health`**. There is no `/healthz`, `/health` or `/readyz`, and the application's own `/openapi.json`, `/docs` and `/redoc` are closed and stay closed. A probe pointed at an endpoint that does not exist reports a fault that is not there, which is its own kind of blindness.

## Measuring cost in something that does not lie

Wall-clock timings drift with cache state, machine load and dataset size, so a screen that felt fine in development can be a different program in production. Connect measures query cost as **statements issued**, which is stable enough to be a regression test.

| Surface | Before | After |
|---|---|---|
| The Owner's customer list | 5,574 | 3 |
| Triage strip | 83 | 11, flat with page size |
| Workspace console | 89 | 17, flat with page size |
| Home | 133 | 15, flat |

The word doing the work in that table is *flat*. A count that grows with the page is a defect that arrives with the business's success and not before, which is why the shape of the number matters more than its value. [Query cost](/docs/technology/query-cost/) covers the measurement.

## What not to record

- **Message content in a log.** It already lives in the record it belongs to; a second copy in a log is a second place to leak from and a second thing to delete on request.
- **Secrets, keys and tokens.** Provider credentials are sealed on save and never echoed back to a screen — a log that prints one has undone that in a line.
- **Raw provider errors with identifiers in them**, in anything a customer or tenant can read.
- **Anything you cannot delete.** A trail that cannot honour a deletion request is a liability wearing a compliance costume.

> **Note** The trail is an accountability record, not a debugging firehose. Keeping it small is what makes it survivable to keep for a long time, and length is the property that makes it useful at all.

## Questions

### How is this different from ordinary application logging?

Logging records that code ran. The audit trail records that a decision was taken, under a named rule, with a result. They answer different questions and have different lifetimes: logs are for the next hour, the trail is for the conversation you have three months later.

### Can a tenant see their own trail?

Yes. Decision Log and activity are the same implementation for both audiences, scoped to the workspace like every other record. A tenant sees their workspace and no part of anyone else's.

### What if the trail and the customer disagree about a message?

The provider acknowledgement stored with the message is what settles it. That is the point of requiring evidence for 'sent' rather than treating a completed function call as proof — see [evidence](/docs/technology/evidence/).

## Related

- [Audit logs](https://connectbyjbrh.com/docs/technology/audit-log/)
- [Observability](https://connectbyjbrh.com/docs/technology/observability/)
- [Query cost](https://connectbyjbrh.com/docs/technology/query-cost/)
- [Deriving control state from the log instead of storing it](https://connectbyjbrh.com/research/derived-control-state/)
- [Evidence in an agent system](https://connectbyjbrh.com/docs/technology/evidence/)

## What this page is based on

- Connect architecture source pack — docs-source/sources/GENERAL.md §5, §10 and §11, the audit trail, health endpoint and measured query costs
- Connect capability registry (docs-source/facts.py) — audit_trail, needs_you, MEASURED
- `backend/app/audit.py`, `audit_api.py` — the accountability trail
