Libraries
Ship evlog inside an npm package so every host, and every agent calling it, gets errors with a code, a cause, and a fix instead of a string.

Your package throws new Error('Not Found') when GitHub answers 404. The host catches a string. Its dashboard cannot count it, its support search cannot find it, and the agent that called your tool reads "not found" as "the repository does not exist" when the real cause is a token that cannot see a private repo. The agent retries with a different owner, fails again, opens your docs, and spends a few thousand tokens learning what one sentence in the error could have said.

A catalog puts that sentence in the error. This is what the two versions hand a consumer:

throw new Error('Not Found')

// what the host or the agent receives
// Error: Not Found

The second error is the same 404. It costs the consumer one read instead of a loop, and it costs you the four sentences you would otherwise write in a support reply.

The github_tools examples in this section come from @github-tools/sdk, a typed GitHub tool layer for AI agents that ships an evlog catalog of eleven errors. It is a real package with real consumers, so its entries show what a catalog looks like after contact with production. Where a page needs a generic scaffold instead, it uses mylib.

Add evlog to my library or SDK

What this section answers

You are about to…Read
Log from library code without stealing the host's configurationEmitting Events
Replace throw new Error() with a catalog the host can routeStructured Errors
Write why and fix so an agent recovers without opening your docsErrors Agents Can Act On
Turn the catalog into a reference page, a JSON file, and an llms.txt sectionExporting the Catalog
Convert an existing package with thirty bare throws, in orderMigrating
Stop a renamed code or field from breaking a host silentlyTesting

The contract

Your package emits. The host configures. Where events go, which ones survive sampling, and what gets redacted is decided by the application's initLogger() call, and library code never makes that call: initLogger() writes process-wide state shared by every evlog copy of the same major, and the last call wins. A library that calls it at import time replaces the host's drain for the whole process with a single require.

That one rule settles the decisions on Emitting Events: which API you use, where the package name goes, and why a library accepts a request logger as a parameter instead of building one. Nothing on the error pages touches configuration: a catalog is a module of factories, and throwing one is what makes the host's pipeline useful.

What it costs

evlog becomes a peer dependency of your package, so a host that never installed it gets one more install. The process shares one configuration per evlog major, so you pin your peer range to a single major and document it. Each catalog entry is four sentences you maintain: the why and fix go stale when the upstream API changes, and a wrong fix misleads an agent faster than no fix at all. And the emit-only contract is a real constraint: your package cannot route its own events anywhere, which is the point.

For the API underneath this section, Structured Errors covers createError and catalogs as an application uses them, and Wide Events covers the event model.