Skip to content

feat(chat): always-on system context manual injected into every agent dispatch#295

Merged
jaylfc merged 1 commit into
masterfrom
feat/agent-system-manual
May 1, 2026
Merged

feat(chat): always-on system context manual injected into every agent dispatch#295
jaylfc merged 1 commit into
masterfrom
feat/agent-system-manual

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented May 1, 2026

Summary

  • Adds tinyagentos/agent_manual.py with build_manual(channel, agent_name, leads) -> str — a pure function, no IO, no globals beyond constant strings. Returns a markdown operating manual covering @-mention routing, project kanban verbs, and lead/non-lead status, branched per channel type and agent role.
  • DM channels get a minimal header + 1-on-1 stub (no routing section, no verbs, no lead section).
  • Group/topic channels get the mentions section + quick reference. Project a2a channels additionally get task verbs and the correct lead/non-lead section based on agent_name in leads.
  • Injects the manual as role: "system" at context[0] in agent_chat_router.py (after build_context_window, before the per-recipient loop). Built per-agent so lead vs non-lead text is correct for each recipient.
  • 24 new unit tests in tests/test_agent_manual.py and 3 new end-to-end tests in tests/test_agent_chat_router.py. All 49 tests in both files pass. 199 tests pass across the wider suite (1 unrelated disk-full environmental error in test_routes_beads.py).

Token count

Longest branch (project a2a, lead agent): 417 estimated tokens (words × 1.3 heuristic; 1869 chars, 321 words). Well within the 500-token budget.

Hook point

tinyagentos/agent_chat_router.py lines 145–170 (after context = build_context_window(...), inside the per-recipient for agent_name in recipients: loop, before bridge.enqueue_user_message). The leads list is extracted from settings.get("leads") once before the loop; build_manual is called per-agent so each agent gets the correct lead/non-lead branch.

No conflicts with in-flight PRs

Test plan

  • pytest tests/test_agent_manual.py — 24 tests covering all channel type branches, empty leads list, token budget
  • pytest tests/test_agent_chat_router.py — all pre-existing tests pass; 3 new e2e tests verify manual injected at context[0] with correct lead/non-lead text
  • Manual review: build_manual is a pure function (no IO, no side effects)
  • Manual review: injected message is role: "system" in router
  • Manual review: DM, group (no project), and project a2a branches render correctly

Summary by CodeRabbit

  • New Features
    • Agents now receive automatically generated operating manuals as system context with instructions tailored to channel type (direct message, group, or project) and agent role designation (lead or non-lead contributor). This ensures agents have contextually relevant guidance for routing messages and executing tasks appropriately.

…ispatch

Adds agent_manual.py with build_manual() — a pure function that returns a
per-agent operating manual (≤500 tokens) covering @-mention routing, project
task verbs, and lead/non-lead status. The router prepends it as role:system
before the conversation history on every chat dispatch so agents always know
the channel primitives without per-session briefs.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

📝 Walkthrough

Walkthrough

A new build_manual() function generates agent-specific operating manual text based on channel type, project configuration, and agent role. The router integrates this by injecting per-recipient system-role messages containing the manual before enqueuing payloads. Comprehensive tests validate manual generation logic and context injection behavior across DM, group, and A2A project channels.

Changes

Cohort / File(s) Summary
Manual Generation Module
tinyagentos/agent_manual.py
New module introducing build_manual() function that conditionally constructs markdown operating manual text based on channel type (dm, group/topic, a2a), project presence, and agent lead status. Includes header, routing guidance, task-verb instructions, and quick-reference sections.
Router Integration
tinyagentos/agent_chat_router.py
Modified to compute leads, invoke build_manual() for each recipient, and prepend the generated manual as a system-role message to the context. Switches enqueued payload from shared context to augmented per-recipient agent-context.
Manual Function Tests
tests/test_agent_manual.py
Full test suite validating build_manual() output across DM, group, and A2A project channels. Asserts presence/absence of expected sections (headers, routing, task verbs, lead directives, quick-reference) and enforces token-budget heuristics (DM <200 tokens, project-lead <500 tokens).
Router Context Tests
tests/test_agent_chat_router.py
New A2A project-channel scenarios verifying system-context injection in _route. Asserts context is non-empty, confirms manually injected system message with expected text, and validates content branches correctly between lead and non-lead recipients.

Sequence Diagram

sequenceDiagram
    actor User
    participant Router as AgentChatRouter
    participant ManualBuilder as build_manual()
    participant Context as Message Context
    participant Queue as bridge.enqueue_user_message

    User->>Router: sends message in channel
    Router->>ManualBuilder: invoke for each recipient<br/>(channel, agent_name, leads)
    ManualBuilder->>ManualBuilder: analyze channel type & role
    ManualBuilder-->>Router: return agent-specific manual text
    Router->>Context: prepend {"role": "system",<br/>"content": manual} to context
    Router->>Queue: enqueue message with<br/>per-recipient agent_context
    Queue-->>User: message routed to recipient<br/>with context-injected instructions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 hops excitedly

Per-recipient wisdom flows,
Context blooms where knowledge grows,
Lead and non-lead paths align,
Agent manuals, oh so fine!
Routing truth in every line. 🌿✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: injecting an always-on system context manual into agent dispatches.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/agent-system-manual

Review rate limit: 9/10 reviews remaining, refill in 6 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tinyagentos/agent_chat_router.py`:
- Around line 171-172: The current code unconditionally prepends
build_manual(channel, agent_name, leads) into agent_context which injects
channel-routing and visibility rules into threaded deliveries; modify the logic
where agent_context is built (the lines that set manual_text and agent_context)
to detect when thread_id is set and either (a) call a new thread-specific manual
generator (e.g., build_thread_manual(channel, agent_name, leads, thread_id))
that omits or replaces routing/visibility sections, or (b) call build_manual
with a flag (e.g., build_manual(..., for_thread=True)) so it suppresses
routing/visibility content for threads; ensure resolve_thread_recipients()
remains the single source of truth for visibility when thread_id is present and
use that branch to produce the appropriate manual_text or no routing text at all
before composing agent_context.

In `@tinyagentos/agent_manual.py`:
- Around line 97-122: build_manual currently ignores settings["response_mode"]
and always injects _SECTION_MENTIONS for group/topic channels; update
build_manual to read response_mode = settings.get("response_mode", "lively") (or
similar) and branch when channel_type in ("group","topic") to append the correct
mention/visibility copy based on response_mode (e.g., append
_SECTION_MENTIONS_QUIET when response_mode == "quiet" and append the existing
_SECTION_MENTIONS or a new _SECTION_MENTIONS_LIVELY when response_mode ==
"lively"), leaving DM and A2A logic (project_id/is_a2a, _SECTION_TASK_VERBS,
_SECTION_LEAD_IS/_SECTION_NON_LEAD, _SECTION_QUICK_REF) unchanged; add any new
constants for the alternative text if needed and ensure references use settings
and response_mode so the manual matches the router behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9cb34d8f-86ed-4fb5-8c84-4da8cf98e60c

📥 Commits

Reviewing files that changed from the base of the PR and between e44e431 and b7d1fb7.

📒 Files selected for processing (4)
  • tests/test_agent_chat_router.py
  • tests/test_agent_manual.py
  • tinyagentos/agent_chat_router.py
  • tinyagentos/agent_manual.py

Comment on lines +171 to +172
manual_text = build_manual(channel, agent_name, leads)
agent_context = [{"role": "system", "content": manual_text}, *context]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Avoid injecting the channel-routing manual into thread deliveries as-is.

When thread_id is set, Lines 54-58 route through resolve_thread_recipients() instead of the normal channel quiet/lively rules. Prepending the same manual here means a threaded recipient can be told they receive every channel message or only @-mentions, even though visibility is now governed by the thread resolver. Please add a thread-specific manual branch, or suppress the routing/visibility sections for threaded dispatches.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tinyagentos/agent_chat_router.py` around lines 171 - 172, The current code
unconditionally prepends build_manual(channel, agent_name, leads) into
agent_context which injects channel-routing and visibility rules into threaded
deliveries; modify the logic where agent_context is built (the lines that set
manual_text and agent_context) to detect when thread_id is set and either (a)
call a new thread-specific manual generator (e.g., build_thread_manual(channel,
agent_name, leads, thread_id)) that omits or replaces routing/visibility
sections, or (b) call build_manual with a flag (e.g., build_manual(...,
for_thread=True)) so it suppresses routing/visibility content for threads;
ensure resolve_thread_recipients() remains the single source of truth for
visibility when thread_id is present and use that branch to produce the
appropriate manual_text or no routing text at all before composing
agent_context.

Comment on lines +97 to +122
channel_type = channel.get("type") or ""
project_id = channel.get("project_id")
settings = channel.get("settings") or {}
is_a2a = settings.get("kind") == "a2a"

# DM: header + stub only.
if channel_type == "dm":
return _HEADER + _DM_STUB

# Group / topic channels.
parts = [_HEADER]

# Section 1: @-mention routing (group and topic channels).
if channel_type in ("group", "topic"):
parts.append(_SECTION_MENTIONS)

# Sections 2 + 3: project a2a only.
if project_id and is_a2a:
parts.append(_SECTION_TASK_VERBS)
if agent_name in leads:
parts.append(_SECTION_LEAD_IS)
else:
parts.append(_SECTION_NON_LEAD)

# Section 4: always for non-DM.
parts.append(_SECTION_QUICK_REF)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the manual respect response_mode.

build_manual() never looks at settings["response_mode"], but Line 67 and Lines 96-99 in tinyagentos/agent_chat_router.py still fan lively channels out to every non-muted member. In a lively group/A2A channel this manual can tell agents “A reply with no @-tag reaches NO ONE” and “You only see messages where you're explicitly @-tagged” even though the router does the opposite. Please branch the mention/visibility copy on quiet vs lively mode before injecting it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tinyagentos/agent_manual.py` around lines 97 - 122, build_manual currently
ignores settings["response_mode"] and always injects _SECTION_MENTIONS for
group/topic channels; update build_manual to read response_mode =
settings.get("response_mode", "lively") (or similar) and branch when
channel_type in ("group","topic") to append the correct mention/visibility copy
based on response_mode (e.g., append _SECTION_MENTIONS_QUIET when response_mode
== "quiet" and append the existing _SECTION_MENTIONS or a new
_SECTION_MENTIONS_LIVELY when response_mode == "lively"), leaving DM and A2A
logic (project_id/is_a2a, _SECTION_TASK_VERBS,
_SECTION_LEAD_IS/_SECTION_NON_LEAD, _SECTION_QUICK_REF) unchanged; add any new
constants for the alternative text if needed and ensure references use settings
and response_mode so the manual matches the router behavior.

@jaylfc jaylfc merged commit 5aaf8e3 into master May 1, 2026
8 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.

1 participant