Skip to content

Commit 135638f

Browse files
committed
restored steering message
1 parent 46a8cc0 commit 135638f

7 files changed

Lines changed: 15 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Fixed
1111

12-
- `TaskAgent._inject_steering` now injects steer text as a single `<event name="task.steered">` user message with a priority directive line ("User has steered your task. Override and prioritize your current plan with the instruction below.") followed by the raw steer text. Same event-xml shape as `task.progress` / `task.cancelled` the agent already reads — without it, the steer was just another peer instruction to the original task description (which is itself a plain user message). Orchestrator side drops its now-redundant `"Steering instruction: "` text prefix.
12+
- `TaskAgent._inject_steering` now injects steer text as a single `<event name="task.steered">` user message with a short priority line followed by the raw steer text inline. Same event-xml shape as `task.progress` / `task.cancelled` the agent already reads — without it, the steer was just another peer instruction to the original task description (which is itself a plain user message). Orchestrator side drops its now-redundant `"Steering instruction: "` text prefix.
1313
- `start_task` and `steer_task` now pre-flight the target's finishing state. If the in-process TaskAgent has already called `finished` (or been cancelled), the steer would race the terminal turn and silently drop. `start_task` handles this transparently: the public entrypoint waits up to `TASK_STEER_CLOSING_WAIT_SECONDS` (default 5s) for the slot to free, then retries the start cleanly — the LLM never sees the intermediate state. Explicit `steer_task` returns `error: "task_closing"` for the LLM to chain `start_task` itself. Personal and corp in-process ships symmetric; BYOA skips the check.
1414
- Voice agent prompt: removed the contradictory "do NOT call start_task if all slots are occupied" line; added a short note that for steered instructions the agent should read the `task.completed` message and mention any unfulfilled intent to the commander.
1515

src/gradientbang/prompts/agents/task_agent.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Approach each task methodically:
1616

1717
## Steering Updates
1818

19-
If you receive a user message beginning with "Steering instruction:", treat it as an update to the current task plan. Integrate it and continue.
19+
If you receive a `<event name="task.steered">` user message, treat it as a priority update to the current task plan. Integrate the inline instruction and continue.
2020

2121
## Historical Event Queries
2222

src/gradientbang/prompts/agents/voice_agent.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Functions requiring a task (use `start_task` immediately, in the same response):
112112
- Each corporation ship adds 1 task slot, up to a maximum of 3.
113113
- A player can own more than 3 corporation ships, but only 3 can run tasks at the same time.
114114

115-
You may call `start_task` multiple times in a single response to fill available slots, or to send an additional instruction into a slot that's already in use (it auto-steers into the running task with a priority directive — the task reassesses on its next turn).
115+
You may call `start_task` multiple times in a single response to fill available slots, or to send an additional instruction into a slot that's already in use (it auto-steers into the running task as a priority update — the task reassesses on its next turn).
116116
Check the `Active tasks:` line in `status.snapshot` to see which slots are in use.
117117

118118
When `task.completed` fires for a task that received steered instructions, read what the agent actually did. If an intent you steered in wasn't fulfilled, mention it to the commander — they can ask you to start it fresh if they still want it.

src/gradientbang/runtime/orchestrator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2759,8 +2759,8 @@ async def _handle_start_task_attempt(self, params: FunctionCallParams) -> dict:
27592759
# Phase: existing-task routing.
27602760
# If this ship already has an active task, auto-steer the new
27612761
# instruction into the running task. The TaskAgent wraps the
2762-
# steer with a <priority> directive on injection so it
2763-
# outranks the original task instruction (see
2762+
# steer in a task.steered event with a short priority hint so
2763+
# it outranks the original task instruction (see
27642764
# TaskAgent._inject_steering). If the active task is already
27652765
# finishing, the steer would race the terminal turn and
27662766
# silently drop — `_steer_existing_task` returns `task_closing`
@@ -3078,8 +3078,8 @@ async def _steer_existing_task(
30783078
if not steering_text:
30793079
return {"success": False, "error": "Empty steering instruction"}
30803080
# No "Steering instruction:" prefix here — TaskAgent wraps the text
3081-
# with a structured priority directive before injecting into LLM
3082-
# context (see TaskAgent._inject_steering).
3081+
# in a task.steered event before injecting into LLM context (see
3082+
# TaskAgent._inject_steering).
30833083

30843084
# Pre-flight: if the target in-process TaskAgent is in a finishing
30853085
# state, the steer would race the terminal turn and silently drop.

src/gradientbang/runtime/subagents/task_agent.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,15 +1715,13 @@ async def _inject_steering(self, text: str) -> None:
17151715
cleaned = text.strip()
17161716
if not cleaned:
17171717
return
1718-
# Single user message: task.steered event with the steer text inside.
1719-
# Same event-xml shape as task.progress / task.cancelled the agent
1720-
# already reads. The directive line tells the LLM to prioritize this
1721-
# over its original task instruction (which is itself a plain user
1722-
# message — no priority signal without this wrap).
1718+
# Single user message: task.steered event with the steer text inline.
1719+
# This matches the event-message flow the task agent already reads,
1720+
# with one short priority hint before the raw steer instruction.
17231721
steered_xml = (
17241722
'<event name="task.steered">\n'
1725-
"User has steered your task. Override and prioritize your current "
1726-
f"plan with the instruction below.\n{cleaned}"
1723+
"Priority update: revise your plan now; follow this over the original task.\n"
1724+
f"{cleaned}\n"
17271725
"</event>"
17281726
)
17291727
if self._llm_context is not None:

tests/unit/test_task_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,9 @@ async def test_steering_emits_replanning_message(self):
974974
injected = agent._llm_context.add_message.call_args.args[0]
975975
assert injected["role"] == "user"
976976
assert injected["content"].startswith('<event name="task.steered">')
977-
assert "User has steered your task" in injected["content"]
978-
assert "Override and prioritize" in injected["content"]
977+
assert "Priority update: revise your plan now" in injected["content"]
979978
assert "Change direction" in injected["content"]
979+
assert injected["content"].endswith("Change direction\n</event>")
980980

981981
async def test_duplicate_progress_message_is_suppressed_without_new_action_or_event(self):
982982
agent = _make_task_agent()

tests/unit/test_voice_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ async def test_steer_success(self):
703703
assert sent.target == "task_abc123"
704704
assert sent.task_id == full_id
705705
# No "Steering instruction:" prefix — TaskAgent wraps the raw text
706-
# with a <priority> directive on injection.
706+
# in a task.steered event on injection.
707707
assert sent.text == "Change course"
708708

709709
async def test_steer_success_for_byoa_agent_targets_bus_name(self):

0 commit comments

Comments
 (0)