Skip to content

Commit 39bd39b

Browse files
resolve the destructive action bug
1 parent 08aba9d commit 39bd39b

2 files changed

Lines changed: 81 additions & 39 deletions

File tree

src/backend/orchestration/orchestration_manager.py

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -603,31 +603,46 @@ async def _evaluate_team_scope(self, workflow, task_text: str) -> Optional[dict]
603603
examples_block = "\n".join(example_lines) or "- (none provided)"
604604

605605
system_prompt = (
606-
"You are a strict scope classifier for a specialized multi-agent "
607-
"team. Decide whether a user's request falls within THIS team's "
608-
"specialization.\n\n"
606+
"You are a strict feasibility classifier for a specialized "
607+
"multi-agent team. Decide whether a user's request can actually be "
608+
"fulfilled by THIS team — considering BOTH (A) its specialization "
609+
"and (B) what its agents are actually able to DO.\n\n"
609610
"A team is defined ENTIRELY by its stated purpose, the specific "
610611
"agents it has and what each does, the data/knowledge those agents "
611612
"work with, and its representative example tasks.\n\n"
612613
"Rules:\n"
613614
"- IN SCOPE only if the request clearly matches this team's "
614-
"specialization and could be fulfilled by these agents using their "
615-
"data.\n"
616-
"- OUT OF SCOPE if the request belongs to a DIFFERENT "
617-
"specialization, even when superficially related or in a broadly "
618-
"similar field (e.g. drafting a product press release is NOT the "
619-
"same specialization as generating retail social-media content; HR "
620-
"onboarding is NOT product marketing; contract/NDA compliance is "
615+
"specialization AND the requested action is something these agents "
616+
"can actually perform with their described capabilities and data.\n"
617+
"- OUT OF SCOPE (kind=\"domain\") if the request belongs to a "
618+
"DIFFERENT specialization, even when superficially related or in a "
619+
"broadly similar field (e.g. drafting a product press release is NOT "
620+
"the same specialization as generating retail social-media content; "
621+
"HR onboarding is NOT product marketing; contract/NDA compliance is "
621622
"NOT RFP evaluation).\n"
623+
"- OUT OF SCOPE (kind=\"capability\") if the request asks the team to "
624+
"perform an ACTION its agents cannot actually do. Agents generally "
625+
"only retrieve, look up, analyze, summarize, or generate content "
626+
"using their data. Unless an agent's description EXPLICITLY says it "
627+
"can do so, the team CANNOT delete, erase, purge, remove, modify, "
628+
"update, overwrite, or otherwise change stored data, and cannot "
629+
"execute real-world side effects (place/cancel orders, send emails, "
630+
"make payments, provision/deactivate accounts). Treat such requests "
631+
"as OUT OF SCOPE — never let the team pretend it performed a "
632+
"destructive or state-changing action it cannot actually perform.\n"
622633
"- If the request is genuinely ambiguous or a reasonable subset of "
623634
"the example tasks, treat it as IN SCOPE.\n\n"
624635
"Respond with ONLY a compact JSON object and nothing else:\n"
625-
'{"in_scope": true|false, "reason": "<one sentence>", '
636+
'{"in_scope": true|false, "kind": "domain"|"capability"|"", '
637+
'"reason": "<one sentence>", '
626638
'"message": "<empty string if in scope; otherwise a short, polite '
627-
"message telling the user this request is outside this team's scope "
628-
"and that they should switch to the appropriate team and try again. "
629-
"Do NOT name, recommend, or guess any specific team; do NOT list "
630-
'what this team specializes in>"}'
639+
"message. If kind=domain, say the request is outside this team's "
640+
"scope and the user should switch to the appropriate team and try "
641+
"again. If kind=capability, say this team cannot perform the "
642+
"requested action (e.g. deleting or modifying stored data) and can "
643+
"only help with the kinds of tasks its agents support; make clear "
644+
"that NO data was changed. In both cases: do NOT name, recommend, or "
645+
'guess any specific team; do NOT list what this team specializes in>"}'
631646
)
632647
user_prompt = (
633648
f"TEAM NAME: {getattr(team_config, 'name', '')}\n"
@@ -653,16 +668,25 @@ async def _evaluate_team_scope(self, workflow, task_text: str) -> Optional[dict]
653668
return None
654669

655670
in_scope = bool(parsed.get("in_scope", True))
671+
kind = str(parsed.get("kind", "") or "").strip().lower()
656672
message = str(parsed.get("message", "") or "").strip()
657673
if not in_scope and not message:
658-
message = (
659-
"This request appears to be outside the scope of the selected "
660-
"team, so it cannot be handled reliably here. Please switch to "
661-
"the appropriate team and try again."
662-
)
674+
if kind == "capability":
675+
message = (
676+
"This team is not able to perform the requested action "
677+
"(such as deleting or modifying stored data). No data has "
678+
"been changed. It can only help with the kinds of tasks its "
679+
"agents support. Please try a supported request instead."
680+
)
681+
else:
682+
message = (
683+
"This request appears to be outside the scope of the "
684+
"selected team, so it cannot be handled reliably here. "
685+
"Please switch to the appropriate team and try again."
686+
)
663687
self.logger.info(
664-
"[SCOPE-GATE] in_scope=%s reason=%s",
665-
in_scope, parsed.get("reason", ""),
688+
"[SCOPE-GATE] in_scope=%s kind=%s reason=%s",
689+
in_scope, kind, parsed.get("reason", ""),
666690
)
667691
return {"in_scope": in_scope, "message": message}
668692
except Exception as e: # fail-open: never block a task on classifier error
@@ -749,8 +773,11 @@ async def _handle_out_of_scope(
749773
MStep(
750774
agent="MagenticManager",
751775
action=(
752-
"Inform the user that this request is out of scope for the "
753-
"selected team and suggest a suitable team."
776+
"Inform the user that this request cannot be handled by the "
777+
"selected team — either because it falls outside the team's "
778+
"scope or because the team's agents cannot perform the "
779+
"requested action (such as deleting or modifying data) — and "
780+
"that no data was changed."
754781
),
755782
)
756783
]

src/backend/orchestration/plan_review_helpers.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,32 @@ def get_magentic_prompt_kwargs(
100100
101101
TEAM SCOPE POLICY (CRITICAL — EVALUATE THIS FIRST, BEFORE ANY OTHER RULE):
102102
This team can ONLY handle requests that fall within the collective expertise of
103-
its listed agents. Each agent's description above tells you its domain and the
104-
data/knowledge it works on — that, and nothing else, defines the team's scope.
105-
106-
Judge whether the user's request is covered by at least one listed agent's domain:
107-
- IN SCOPE: at least one agent's expertise/data is clearly relevant → plan normally.
108-
- OUT OF SCOPE: NO listed agent's domain covers the request (e.g. a contract /
109-
compliance request given to a marketing or RFP team, or an HR / onboarding
110-
request given to a product-marketing team). In this case you MUST NOT invoke any
111-
domain agent. Output a plan with EXACTLY ONE step and nothing else:
112-
[{{"agent": "MagenticManager", "action": "Inform the user that this request is out of scope for this team and that they should switch to the appropriate team and try again, without naming any specific team."}}]
103+
its listed agents AND that ask for actions its agents can actually perform. Each
104+
agent's description above tells you its domain and the data/knowledge it works on —
105+
that, and nothing else, defines the team's scope and capabilities.
106+
107+
Judge whether the user's request is (a) covered by at least one listed agent's
108+
domain AND (b) an action the agents can actually perform:
109+
- IN SCOPE: at least one agent's expertise/data is relevant AND the requested
110+
action is something the agents can do → plan normally.
111+
- OUT OF SCOPE — WRONG DOMAIN: NO listed agent's domain covers the request (e.g. a
112+
contract / compliance request given to a marketing or RFP team, or an HR /
113+
onboarding request given to a product-marketing team).
114+
- OUT OF SCOPE — UNSUPPORTED ACTION: the domain may match, but the request asks for
115+
an action the agents CANNOT perform. Agents generally only retrieve, analyze,
116+
summarize, or generate content from their data. Unless an agent's description
117+
explicitly says otherwise, the team CANNOT delete, erase, remove, modify, update,
118+
or overwrite stored data, nor execute real-world side effects (placing/cancelling
119+
orders, sending emails, making payments). NEVER pretend such an action was done
120+
(e.g. "Delete all data and order history for customer X").
121+
In EITHER out-of-scope case you MUST NOT invoke any domain agent. Output a plan with
122+
EXACTLY ONE step and nothing else:
123+
[{{"agent": "MagenticManager", "action": "Inform the user that this request cannot be handled by this team — because it is outside the team's scope, or because the team cannot perform the requested action such as deleting or modifying data — and that no data was changed, without naming any specific team."}}]
113124
114125
When out of scope, the mandatory-inclusion rule below does NOT apply — the lone
115126
MagenticManager step IS the complete, valid plan. Only take this path when the
116-
request is genuinely outside every agent's domain; when in doubt, plan normally.
127+
request is genuinely outside every agent's domain or asks for an action no agent can
128+
perform; when in doubt, plan normally.
117129
"""
118130

119131
plan_append = scope_policy + """
@@ -161,10 +173,13 @@ def get_magentic_prompt_kwargs(
161173
162174
FINAL ANSWER RULES:
163175
- If the approved plan was a single out-of-scope MagenticManager step (no domain
164-
agents ran), your final answer is a brief, polite message that states the
165-
request is out of scope for this team and that the user should switch to the
166-
appropriate team and try again. Do NOT name, recommend, or guess any specific
167-
team, and do NOT attempt to answer the out-of-scope request itself.
176+
agents ran), your final answer is a brief, polite message. If the request was
177+
outside the team's domain, state that it is out of scope and that the user should
178+
switch to the appropriate team and try again. If the request asked for an action
179+
the team cannot perform (such as deleting or modifying stored data), state that
180+
the team cannot perform that action and that NO data was changed. Do NOT name,
181+
recommend, or guess any specific team, do NOT claim any action was performed, and
182+
do NOT attempt to answer the out-of-scope request itself.
168183
- Compile ONLY from messages agents actually produced. Quote verbatim where appropriate.
169184
- Do NOT fabricate URLs, results, or content that no agent produced.
170185
- If a required agent step did not run, state it plainly — do not pretend it did.

0 commit comments

Comments
 (0)