Summary
agent_control_server always emits uvicorn's built-in uvicorn.access request log and provides no way to turn it off. When the server is embedded in a host that already emits its own structured request log (via its own ASGI middleware), this produces a duplicate line per request — often in a different format. Add an opt-out flag so the built-in access log can be disabled without affecting error/app logging.
Background
run() in server/src/agent_control_server/main.py calls uvicorn.run(app, ...) with log_level set but no control over uvicorn's access log:
uvicorn_kwargs: dict[str, Any] = {
"host": settings.host,
"port": settings.port,
"log_level": get_uvicorn_log_level_name(_default_log_level()).lower(),
}
if not should_configure_logging():
uvicorn_kwargs["log_config"] = None
uvicorn.run(app, **uvicorn_kwargs)
There's already a precedent for this kind of opt-out: AGENT_CONTROL_CONFIGURE_LOGGING=false lets an embedder own logging config and passes log_config=None to uvicorn. But that flag does not stop the access log — uvicorn's Config.configure_logging() unconditionally runs its log_level branch (independent of log_config), which resets uvicorn.access to INFO. So even with configure_logging=false, and even if the embedder raises uvicorn.access to WARNING beforehand, uvicorn clobbers it back to INFO and the access line is emitted anyway.
The only uvicorn lever that reliably suppresses the access log regardless of level or config ordering is the access_log kwarg. When access_log=False, uvicorn clears uvicorn.access's handlers and sets propagate=False, so its per-connection hasHandlers() gate is False and it never calls access_logger.info(...) at all. It's currently not plumbed through.
Proposed change
Add a settings field and pass it through to uvicorn.run, defaulting to current behavior (True).
server/src/agent_control_server/config.py — in LoggingSettings:
access_log: bool = _env_alias_field(True, "AGENT_CONTROL_ACCESS_LOG")
server/src/agent_control_server/main.py — in run():
uvicorn_kwargs: dict[str, Any] = {
"host": settings.host,
"port": settings.port,
"log_level": get_uvicorn_log_level_name(_default_log_level()).lower(),
"access_log": LoggingSettings().access_log,
}
Acceptance criteria
Use case
Embedders (e.g. a service that injects its own request-logging middleware onto the agent-control app) can set AGENT_CONTROL_ACCESS_LOG=false to make their own middleware the sole request log, eliminating the duplicate line.
Summary
agent_control_serveralways emits uvicorn's built-inuvicorn.accessrequest log and provides no way to turn it off. When the server is embedded in a host that already emits its own structured request log (via its own ASGI middleware), this produces a duplicate line per request — often in a different format. Add an opt-out flag so the built-in access log can be disabled without affecting error/app logging.Background
run()inserver/src/agent_control_server/main.pycallsuvicorn.run(app, ...)withlog_levelset but no control over uvicorn's access log:There's already a precedent for this kind of opt-out:
AGENT_CONTROL_CONFIGURE_LOGGING=falselets an embedder own logging config and passeslog_config=Noneto uvicorn. But that flag does not stop the access log — uvicorn'sConfig.configure_logging()unconditionally runs itslog_levelbranch (independent oflog_config), which resetsuvicorn.accessto INFO. So even withconfigure_logging=false, and even if the embedder raisesuvicorn.accessto WARNING beforehand, uvicorn clobbers it back to INFO and the access line is emitted anyway.The only uvicorn lever that reliably suppresses the access log regardless of level or config ordering is the
access_logkwarg. Whenaccess_log=False, uvicorn clearsuvicorn.access's handlers and setspropagate=False, so its per-connectionhasHandlers()gate isFalseand it never callsaccess_logger.info(...)at all. It's currently not plumbed through.Proposed change
Add a settings field and pass it through to
uvicorn.run, defaulting to current behavior (True).server/src/agent_control_server/config.py— inLoggingSettings:server/src/agent_control_server/main.py— inrun():Acceptance criteria
access_logonLoggingSettings, defaulting toTrue(no behavior change for existing users).AGENT_CONTROL_ACCESS_LOG(consistent withAGENT_CONTROL_CONFIGURE_LOGGING).AGENT_CONTROL_ACCESS_LOG=false, nouvicorn.accessline is emitted for requests, and this holds whetherconfigure_loggingis on or off.uvicorn.error, application loggers) is unaffected.AGENT_CONTROL_LOG_*options.Use case
Embedders (e.g. a service that injects its own request-logging middleware onto the agent-control app) can set
AGENT_CONTROL_ACCESS_LOG=falseto make their own middleware the sole request log, eliminating the duplicate line.