Skip to content

core+web: agent-tagged log prefixes; one-shot capability hints; v0.9.50 - #196

Merged
cymoo merged 3 commits into
mainfrom
log-attribution
Aug 11, 2026
Merged

core+web: agent-tagged log prefixes; one-shot capability hints; v0.9.50#196
cymoo merged 3 commits into
mainfrom
log-attribution

Conversation

@cymoo

@cymoo cymoo commented Aug 10, 2026

Copy link
Copy Markdown
Owner

What

Follow-up to the log investigation: two changes that make lovia web console logs attributable and quiet.

Agent-tagged log prefixes

Every log line emitted inside a run now names the agent it belongs to. A new core contextvar lovia.log_config.CURRENT_AGENT is set by RunLoop.stream() for the run's duration (re-set on handoff in _resolve_active, restored when the run ends; nested side-runs shadow and restore the host's tag). The web run-source filter composes it with the existing run source:

before after line from
[user] [user/lovia] the chat run itself
[user] [user/memory-digest] memory curation the chat triggered
(none) [followups] / [titler] parentless helper runs
[subagent:abc] [subagent:abc/researcher] subagent task runs

This is what made the original confusion possible: the memory digest's context.window: unknown line rendered as plain [user] right after the chat's run.done, reading as if the chat run had lost its configured window.

One-shot capability hints

context.window: unknown for ... and tool 'view_image' ... not offering it are static facts about a model, not per-run events — but they re-fired on every bootstrap, including every follow-up/title/memory side-run. Both now log once per process per model (_log_once memo in the loop), keeping the first occurrence's diagnostic value at INFO.

Deliberately not done

Threading the configured context window into helper side-runs: one-shot runs have no history to compact (proactive budgeting is a no-op; reactive overflow rescue works without a window), and the correct wiring is not small — the followup/title model can be a different endpoint than the default profile, and the memory plugin is core so it cannot see web config. Assessment in the session; can be a follow-up if wanted.

Tests

  • filter composition (source+agent, agent-only, task-locality)
  • CURRENT_AGENT set during a run, restored after; nested run shadows and restores
  • both hints logged once across two runs, keyed by model

Full suite: 2310 passed, 41 skipped.

🤖 Generated with Claude Code

Log lines emitted inside a run now carry the running agent's name:
CURRENT_AGENT (lovia.log_config) is set by RunLoop for the run's duration
(updated on handoff, restored on exit), and the web run-source filter
composes it with the run's source into [user/lovia], [user/memory-digest],
[followups]-style prefixes — a side-run a chat triggers is no longer
indistinguishable from the chat itself.

The two static capability hints — 'context.window: unknown' and the
returns_images 'not offering it' gate — now log once per process per
model instead of on every run bootstrap: each helper side-run (follow-ups,
titles, memory curation) repeated them after every chat exchange.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 10, 2026 17:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves log attribution and reduces repetitive bootstrap diagnostics in lovia (core + lovia web) by (1) tagging logs with the currently-running agent name and (2) logging certain static capability/context-window hints only once per process per model. It also bumps the project version to 0.9.50.

Changes:

  • Add lovia.log_config.CURRENT_AGENT (contextvar) and set/reset it in RunLoop.stream() (and re-set on activation) so logs can be attributed to the active agent across handoffs and nested runs.
  • Compose web RUN_SOURCE + CURRENT_AGENT into a single %(run_source)s prefix (e.g. [user/lovia], [user/memory-digest], [followups]) for clearer console logs.
  • Introduce a loop-level _log_once memo to avoid repeating static “context.window unknown” / “tool … not offering it” hints across multiple runs; add tests for both behaviors.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
uv.lock Bump locked package version to 0.9.50.
pyproject.toml Bump project version to 0.9.50.
lovia/init.py Bump __version__ to 0.9.50.
lovia/log_config.py Add CURRENT_AGENT contextvar for per-task agent tagging.
lovia/runtime/loop.py Set/reset CURRENT_AGENT during runs; add _log_once for one-shot hints.
lovia/web/supervisor.py Update run-source log filter to include agent tag in prefixes.
lovia/web/main.py Update logging-format comment to reflect composed prefixes.
tests/workspace/test_workspace_agent.py Add test asserting image-tool gating hint logs once per model.
tests/web/test_subagents.py Extend tests to cover composed [source/agent] and agent-only tags.
tests/runtime/test_loop.py Add tests for CURRENT_AGENT set/restore and nested-run shadowing.
tests/runtime/test_context_window_discovery.py Add test asserting unknown context-window hint logs once per model.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lovia/web/supervisor.py
Comment on lines 89 to 92
def filter(self, record: logging.LogRecord) -> bool:
source = RUN_SOURCE.get()
record.run_source = f"[{source}] " if source else ""
tag = "/".join(p for p in (RUN_SOURCE.get(), CURRENT_AGENT.get()) if p)
record.run_source = f"[{tag}] " if tag else ""
return True

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3d062d7: the filter collapses control characters in the composed tag before formatting (isprintable() fast path, so the per-record cost stays a single check). Bracket characters are left alone — they can't fabricate lines, only look odd.

cymoo and others added 2 commits August 11, 2026 01:34
A free-form agent name containing a newline would split the one-line
[source/agent] prefix and fabricate log lines. isprintable() keeps the
per-record cost to a fast check; the collapse runs only on a
pathological name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep the cross-module contract notes (CURRENT_AGENT set by the loop, read
by the web filter; the suppress(ValueError) edge) and drop restated
rationale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cymoo
cymoo merged commit 2d2581e into main Aug 11, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants