Description
Is your feature request related to a problem? Please describe.
Downstream projects created via elizaos create my-agent cannot currently customize the root logger. They can create child loggers with bindings but cannot modify transports, formatting, or other global logging behavior. This limits integration with services like CloudWatch, file logging, or external log aggregators.
- The root logger is created immediately on module import (index.ts), using static env-based config.
- The start command loads project config but doesn’t apply it to logging.
- Loggers created with createLogger() inherit root settings and cannot override transports or formats.
- Each agent runtime gets a child logger with limited ability to adjust formatting or destinations.
Currently Not Possible:
- Add CloudWatch, file, or HTTP transports
- Use structured JSON format beyond LOG_JSON_FORMAT
- Customize or replace root logger behavior
Describe the solution you'd like
Implement a delayed logger initialization flow that:
- Loads project-level config (e.g., logger.config.js) before root logger is created
- Allows registering custom transports, formatters, and levels through that config
- Initializes the root logger after applying project settings
Describe alternatives you've considered
-
trying to gain control over the root-logger or alter it's behavior from the child project via monkey patching. Unfortunately, you can't alter the root logger in this way and even if you could, would only impact log messages AFTER the server startup hands control to the custom agent (when you likely want the startup messages in something like Cloudwatch to help you understand why ElizaOS failed to start)
-
using a separate process to grab logs and send to external services (for example: https://pm2.keymetrics.io/) This can work, but it's not ideal; as you still can't control the format directly.
Additional context
-
The logger is currently initialized in packages/core/src/logger.ts when the module is first imported (module scope), which locks in default configuration before the project runtime begins.
-
The logger uses the pino logger wrapped with a custom InMemoryDestination stream, which supports pretty printing but not external transport plugins.
-
No extension points exist today for adding or replacing transports (e.g., pino.destination() or external streams).
-
Any attempt to modify logging behavior currently requires monkey-patching the logger after runtime starts, which is both brittle and incomplete for capturing early logs (e.g., boot, config load errors).
-
A recent use case required shipping logs to CloudWatch using Pino-compatible transports, but this was not feasible due to the logger being fully initialized before project code could intervene.
I do want to thank the team for all the work you're doing on ElizaOS and this feature request is very much intended in the spirit of making it even better. Directionally, I fully understand what you're doing by separating the core ElizaOS functionality from downstream agents (over which you'd have no control). But some degree of customization by those downstream agents is likely still required for specific deployment use cases.