Skip to main content
This page covers the adapter-specific parts of writing a custom module. For the shared mechanics (file layout, registration, lifecycle) see Writing a custom module. For the full interface reference see AdapterModule.

Minimal Skeleton

Logging

The host owns all logging - your module never creates a logger. The logger it receives in setup already carries your module’s identity (moduleId, moduleType, adapterId), and every entry is tagged type: "module".
  • Call context.logger.redact(patterns) to opt into self-managed reduction. Declare redactionPatterns in your own configSchema and read it back from context.config: the host never supplies patterns for you. Your patterns merge additively on top of a non-disableable baseline (secrets / tokens / passwords / authorization).
  • Use logger.child({ ... }) to scope a logger for a phase or a specific invocation. child accepts only phase/event; the host-owned correlation fields (serviceId, toolId, executionId, …) are merged in by the host and cannot be forged.
  • Emit structured logs with logger.info({ event, ...payload }, "message"). All six levels are available: trace, debug, info, warn, error, fatal.

Full Example

See the HTTP adapter example in the repository for a complete, working adapter that accepts a JSON service definition describing REST endpoints and calls them over HTTP. It stores per-service base URLs in adapterDomain, reads secrets for Authorization, and routes each invocation to the correct endpoint. See ServiceState for the shape of the snapshot the host delivers to hydrateService, and AdapterModule for the full interface contract.
Last modified on August 25, 2026