Skip to content

fix(core): collapse child agent initial input into a single user message#589

Open
Rome-1 wants to merge 1 commit into
usestrix:mainfrom
Rome-1:fix/issue-113-child-input-single-message
Open

fix(core): collapse child agent initial input into a single user message#589
Rome-1 wants to merge 1 commit into
usestrix:mainfrom
Rome-1:fix/issue-113-child-input-single-message

Conversation

@Rome-1

@Rome-1 Rome-1 commented Jun 26, 2026

Copy link
Copy Markdown

Fixes #113

child_initial_input (strix/core/inputs.py) built a child agent's first turn as two or three consecutive {"role": "user"} messages — an inherited-context block (when a parent history exists), an identity line, and the task. That violates the strict user/assistant alternation that providers like Perplexity (sonar-reasoning) and llama.cpp enforce, aborting scans with PerplexityException - ... user or tool message(s) should alternate with assistant message(s). This collapses those parts into a single {"role": "user"} message joined with blank lines, preserving the exact same content while keeping the request well-formed for strict-alternating backends. The consumer in strix/core/execution.py already treats the return value as an opaque message list, so behavior is unchanged for every other provider.

Testing

  • pytest tests/test_inputs.py — 8 passed. New tests assert a single user message (with and without inherited history), that the identity line and task survive, and a parametrized no-consecutive-same-role guard; plus added coverage for the untouched build_root_task builder. Reverting the source change in-tree makes the child-input tests fail (4 failed), confirming they are load-bearing.
  • pytest (full suite) — 46 passed, no regressions.
  • ruff check, ruff format --check, bandit, and pyupgrade --py310-plus are clean on the changed files. (The repo's pinned pre-commit mypy hook crashes with an internal error on the bundled openai SDK on main as well, so mypy is not asserted here.)

…x#113)

Emitting 2-3 consecutive {role: user} messages broke providers that
require strictly alternating roles (Perplexity, llama.cpp). Build a
single user message from a parts accumulator instead. Adds tests/test_inputs.py
covering child_initial_input and build_root_task.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes child_initial_input in strix/core/inputs.py, which previously emitted 2–3 consecutive {"role": "user"} messages, violating the strict turn-alternation requirement of providers like Perplexity (sonar-reasoning) and llama.cpp. The fix collapses the inherited-context block, the identity line, and the task into a single user message joined with \n\n, preserving all content while satisfying strict alternation.

  • strix/core/inputs.py: child_initial_input now builds a parts: list[str], appends each text segment conditionally, and returns a single {"role": "user"} dict. The surrounding call site in execution.py is unaffected.
  • tests/test_inputs.py: New test file with 8 tests — single-message contract (with/without inherited history), content-preservation assertions, a parametrized no-consecutive-role guard, and coverage for build_root_task.

Confidence Score: 5/5

Safe to merge — the change is minimal and surgical, touching only the message-building logic in one function with no side effects on callers.

The fix collapses a well-understood multi-message sequence into a single message without dropping or reordering any content. The call site in execution.py treats the return value as an opaque list, so the reduction from 3 messages to 1 is transparent to all consumers. Tests confirm single-message output, content preservation, and the no-consecutive-role invariant in both the empty-history and non-empty-history cases, and the PR author verified the tests fail on a local revert.

No files require special attention.

Important Files Changed

Filename Overview
strix/core/inputs.py Collapses 2–3 consecutive user messages in child_initial_input into one; content and ordering are preserved, docstring added — no logic regressions visible.
tests/test_inputs.py New test file covering child_initial_input (single-message contract, content preservation, no-consecutive-role guard) and build_root_task (empty config, repo/URL targets, diff-scope). Tests are well-structured and load-bearing.

Reviews (1): Last reviewed commit: "fix: collapse child_initial_input into a..." | Re-trigger Greptile

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.

[BUG] litellm.BadRequestError: PerplexityException – Assumption: Consecutive User Messages in Strix Agent

1 participant