mpfaffenberger / mpfaffenberger/code_puppy
Ctrl+T "steer now" → 400 "Instructions are required" on OpenAI Responses models
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 814
- Forks
- 278
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 76
Description
Summary
A now-mode steer aborts the run with a 400 from the model API when the active model uses the OpenAI Responses API. The same steer with mode="queue" works fine. It looks like the mid-turn steer history-processor appends a ModelRequest without instructions, so the Responses request goes out with empty instructions.
Environment
- code-puppy
0.0.550 - pydantic-ai
1.56.0 - Python
3.14.4(macOS, arm64) - Model served via the OpenAI Responses API (model name
gpt-5.5; endpoint returns{'detail': 'Instructions are required'}, i.e. it requires a non-emptyinstructions).
Steps to reproduce
- Configure a model that uses the OpenAI Responses API.
- Give the agent a multi-step task so it's mid-run.
- While it's running, Ctrl+T and submit a steering message in "steer now" mode (equivalently:
get_message_bus().provide_response(SteerAgentCommand(text="…", mode="now"))). - The next model call fails.
Expected
The steer is injected as a user turn and the run continues (as it does for mode="queue").
Actual
🎯 Injecting steer mid-turn — model will see: 'Actually make it a unit converter …'
Unexpected error: status_code: 400, model_name: gpt-5.5, body: {'detail': 'Instructions are required'}
...
File ".../pydantic_ai/models/openai.py", line 1386, in request_stream
response = await self._responses_create(...)
File ".../pydantic_ai/models/openai.py", line 1681, in _responses_create
raise ModelHTTPError(status_code=status_code, model_name=self.model_name, body=e.body) from e
pydantic_ai.exceptions.ModelHTTPError: status_code: 400, model_name: gpt-5.5, body: {'detail': 'Instructions are required'}
The run aborts; the session is auto-saved and returns to the prompt.
Likely root cause
code_puppy/agents/_steer_processor.py → make_steer_history_processor injects each now-mode steer by appending a bare ModelRequest to the end of the message list:
injected.append(ModelRequest(parts=[UserPromptPart(content=steer_text)]))
new_messages = list(messages) + injected
return new_messages
That ModelRequest carries no instructions. On the OpenAI Responses path, pydantic-ai derives the request's instructions from the (final) ModelRequest, so the call goes out with empty instructions and a Responses endpoint that requires them rejects it with 400.
mode="queue" doesn't hit this because it's drained between turns and replayed via a normal follow-up run, which carries the agent's instructions.
Suggested fix (one of)
- Carry the agent's instructions onto the injected request, e.g.
ModelRequest(parts=[UserPromptPart(content=steer_text)], instructions=<agent instructions>), or - Append the steer as a
UserPromptPartto the existing finalModelRequestinstead of adding a new bare one (so the original request'sinstructionsis preserved).
Workaround
Use mode="queue" for steering on Responses-API models.
Context
Found while prototyping a remote-control plugin (idea discussed in #395). Happy to open a PR for the fix if that's welcome.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in code_puppy/agents/_steer_processor.py at make_steer_history_processor and trace the now-mode path reached by SteerAgentCommand. Compare the injected ModelRequest with the existing message history and the pydantic-ai OpenAI Responses request shown in the traceback. Done means a now-mode steer continues successfully on Responses API models while queue mode remains working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100