Skip to content

Move agent Instructions after Actions and Knowledge, add #action / #knowledge references - #1263

Merged
Paul Lizer (paullizer) merged 3 commits into
Developmentfrom
paullizer-agent-instructions-tab-reorder
Aug 18, 2026
Merged

Paul Lizer (paullizer) merged 3 commits into
Developmentfrom
paullizer-agent-instructions-tab-reorder

Conversation

@paullizer

Copy link
Copy Markdown
Collaborator

Summary

The agent modal asked for Instructions at step 3, before Actions (4) and Assigned Knowledge (5). Authors had to describe behaviour for tools and documents they hadn't selected yet, and the Draft Instructions helper had no idea what the agent would actually be able to do.

This moves Instructions after Actions and Knowledge, and uses that ordering to make instruction authoring context-aware.

Fixes #1257

What changed

1. Step reorder

Basic InfoModel & ConnectionActionsKnowledgeInstructionsAdvancedSummary

Rather than just renumbering, navigation and validation now branch on a named AGENT_STEP_KEYS map instead of hard-coded step numbers, so the modal can be reordered again without hunting magic numbers through showStep(), validateCurrentStep(), and applyAgentTypeVisibility().

2. "Selected Actions & Knowledge" reference panel

A collapsible card at the top of the Instructions step listing each selected action with badges for its enabled capabilities, plus the assigned workspaces, documents, tags, and web sources — each showing its reference token.

3. # autocomplete in the Instruction Brief and the instructions editor

Typing # opens a menu offering the action and knowledge namespaces, then drills down:

  • #action: lists the actions selected in the Actions step. Actions with sub-capabilities (Simple Chat, Microsoft Graph, Chart) open a third level listing only the enabled capability keys.
  • #knowledge: lists documents, workspaces, tags, and web sources in one list with type badges.

Arrow keys to navigate, Tab/Enter to insert, Esc to dismiss, plus mouse hover and click.

Tokens are stored literally so they stay editable and round-trip unchanged when editing an agent:

#action:<ActionDisplayName>
#action:<ActionDisplayName>:<capability_key>
#knowledge:doc:<Document Title>
#knowledge:workspace:<Workspace Name>
#knowledge:tag:<tag>
#knowledge:web:<url>

Values containing a space or colon are wrapped in double quotes, e.g. #knowledge:doc:"Employee Handbook.pdf".

4. Context-aware Draft Instructions

POST /api/agents/draft-instructions now also receives the selected actions with their enabled capabilities and the assigned knowledge configuration. The system prompt documents the token grammar and requires the model to reference only listed actions, capabilities, and documents.

Both fields are optional — omitting them preserves the previous behaviour.

Notable engineering decisions

The trigger scan is a linear reverse scan, not a regex — deliberately. The first implementation used (?:[^\s#"]|"[^"#]*"?)* to describe optional quoted runs. The optional closing quote makes each quoted span ambiguous, so the number of ways to decompose N quoted phrases is exponential. Since parseTrigger runs on every keystroke over a 500-character window, ordinary prose blew up:

input before after
184 chars, 7 quoted phrases 10,221 ms 0.0026 ms
600-char window, worst shape unbounded 0.0046 ms

Instruction text also arrives from other users (shared/global agents, templates), so merely opening such an agent's editor would have hung the tab. locateMentionTrigger() is now a single O(n) reverse scan over a bounded window.

Client-supplied draft context is untrusted prompt text only. It never touches scope, roles, or data access — the existing authorization checks are unchanged. Values are whitespace-collapsed (neutralizing newline-based prompt injection in labels), per-item capped, and bounded by a shared total budget. Per-item caps alone still allowed an ~856 KB prompt (40 actions × 30 capabilities × 400 chars, etc.); _apply_agent_instruction_context_budget() now enforces a combined 8000-character limit with fair rollover so neither block starves the other. Same worst-case payload now yields ~9 KB.

Menu events are split by intent. Text edits (input, changes) may open the menu; caret-only events (keyup, click, cursorActivity) only re-evaluate or close one that is already open. Without that split, clicking anywhere after an existing #… token pops the menu open unrequested.

Foundry agents stay inert. Classic Foundry, New Foundry, and Foundry Workflow manage instructions and tools in Foundry, so the panel, autocomplete, and draft payload all short-circuit for those types.

No new browser dependencies. The vendored SimpleMDE 1.11.2 bundle does not ship CodeMirror's show-hint addon, so the menu is a local static ES module positioned with codemirror.cursorCoords(). Per the repo's local browser assets rule, nothing is loaded from a CDN and there are no dynamic imports.

Testing

New functional tests (21 cases across 3 files, all passing):

File Coverage
test_agent_modal_instructions_step_order.py Step indicator order, #agent-step-N id assignment, AGENT_STEP_KEYS map, absence of the old magic numbers
test_agent_instruction_mention_tokens.py Token grammar and quoting, trigger parsing, linear-scan performance guard, completed-token handling, cleanup and open-gating, item filtering, local-asset and XSS-safe rendering
test_agent_draft_instructions_context.py Prompt context rendering, per-item and total sanitization caps, token guidance, backward compatibility

New UI testui_tests/test_agent_modal_instruction_references.py covers the browser workflow end to end: step order, the reference panel, keyboard and mouse autocomplete in both the brief and the markdown editor, and Foundry inertness.

Also verified with a jsdom harness exercising the real interaction flow (24 checks, including an XSS check with a malicious document title rendered as text).

Route policy tests are unchanged and green — no new Flask routes are added.

Other changes

  • Updated 3 existing UI tests that drove the modal by step number (goToStep(4), goToStep(5)) to look the step up by name via getStepNumber('actions'), so they survive future reorders.
  • Fixed a brittle marker in test_workspace_prompt_markdown_toolbar_fix.py that pinned an exact refreshInstructionsEditor(...) expression. It was already failing on Development (it expected currentAgentType !== 'aifoundry', which HEAD did not have) and is directly coupled to a line this PR touches.
  • Fixed stale "Go back to step 4 to add actions" copy in the summary step — Actions is step 3 now.

Docs and version

  • VERSION 0.250.2080.250.209
  • New docs/explanation/features/AGENT_INSTRUCTION_CONTEXT_REFERENCES.md
  • Release notes entry under v0.250.209

Known limitations (deliberate)

  • Stale tokens are not flagged. If an action or document is deselected after a token was inserted, the token stays. The author stays in control; highlighting/validating stale tokens is deferred to a follow-up.
  • Action-level capabilities are limited to Simple Chat, Microsoft Graph, and Chart. OpenAPI, SQL, and custom actions expose no sub-capability list in the modal, so they complete at the action level.

Screenshots

Instructions step with the reference panel and # autocomplete — worth a quick manual pass in the browser before merge.

Paul Lizer (paullizer) and others added 3 commits August 17, 2026 18:03
The agent modal asked for Instructions at step 3, before Actions (4) and
Assigned Knowledge (5), so authors wrote instructions before knowing what
the agent could actually do, and Draft Instructions had no idea either.

- Reorder steps to Basic Info, Model & Connection, Actions, Knowledge,
  Instructions, Advanced, Summary. Navigation and validation now branch on
  a named AGENT_STEP_KEYS map instead of hard-coded step numbers.
- Add a collapsible "Selected Actions & Knowledge" panel to the Instructions
  step showing each selected action with its enabled capabilities, plus the
  assigned workspaces, documents, tags, and web sources with their tokens.
- Add "#" autocomplete (agent_instruction_mentions.js) to the Instruction
  Brief and the SimpleMDE editor. It drills down namespace -> action ->
  capability, and #knowledge: lists documents, workspaces, tags, and web
  sources with type badges. Tokens such as #action:"Simple Chat":create_group
  are stored literally so they stay editable.
- Send the selected actions and assigned knowledge to
  POST /api/agents/draft-instructions. The payload is untrusted prompt text
  only: it is normalized, per-item capped, and bounded by a shared total
  budget, and never affects authorization.

The trigger scan is a linear reverse scan rather than a regex on purpose. A
pattern describing optional quoted runs is ambiguous and backtracked
exponentially on ordinary prose, so it ran per keystroke at seconds per call.

Adds three functional tests and a Playwright UI test, and updates the UI
tests that drove the modal by step number to look the step up by name.

Fixes #1257

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Round out the entries now that the change is under review as #1263:

- Reference the pull request alongside the issue.
- Note automatic quoting of token values, that document titles containing
  spaces stay searchable, and that the references stay inert for the three
  Foundry agent types.
- Call out the shared total prompt budget and the whitespace collapsing that
  prevents newline-based prompt injection through action or document names.
- Add a Bug Fixes entry for the Summary step telling authors to "go back to
  step 4" for actions, which is step 3 under the new order.

Documentation only, so the application version is unchanged.

Refs #1257

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolves two conflicts, both from Development moving ahead by 14 commits:

- config.py: Development shipped 0.250.213 and had already reused 0.250.209
  for the Yamcs action, so this change is rebased onto 0.250.214.
- release_notes.md: the agent instruction reference entries move under a new
  v0.250.214 heading, stacked above Development's v0.250.213 section.

Version references in the three functional tests, the UI test, and the feature
documentation are updated from 0.250.209 to 0.250.214 to match.

agent_modal_stepper.js merged cleanly. Development added a
'raise_workflow_alert' SimpleChat capability that is opt-in via a new
defaultEnabled flag; getEnabledCapabilitiesForAction() reads capabilities
through getSimpleChatCapabilitiesForAction(), so the capability is correctly
absent from the #action: menu until an author enables it.

Refs #1257

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit bb9d0f0 into Development Aug 18, 2026
11 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