Skip to content

[3/3] Update Copilot plugin to leverage new TypeAgent MCP tools - #2993

Queued
George Ng (GeorgeNgMsft) wants to merge 14 commits into
mainfrom
georgengmsft-structured-action-adapters
Queued

George Ng (GeorgeNgMsft) wants to merge 14 commits into
mainfrom
georgengmsft-structured-action-adapters

Conversation

@GeorgeNgMsft

@GeorgeNgMsft George Ng (GeorgeNgMsft) commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

This PR lets Copilot discover and call TypeAgent actions while reasoning, using the shared service added in #2991 and #2992. It passes inputs directly as structured data, asks the user when confirmation is needed, and returns the full result. Existing natural-language requests and recording commands keep working as before.

  • Add four tools: search, execute, continue, and cancel, available in Direct and MCP modes.
  • Keep calls connected to the same TypeAgent conversation, with safe reconnects and no automatic replay after a lost connection.
  • Show complete confirmations, questions, and forms. Resume only with the user’s answer, and preserve failures or uncertain outcomes.
  • Use the same connection client for the Copilot plugin and native MCP server. Keep validation and execution policy in Dispatcher.
  • Preserve main’s newer plugin extension and fix cases where pending input or execution errors could look like success.
  • Add end-to-end coverage and document the workflow and limitations.

Flow: Discover an action → send typed inputs → ask the user if needed → resume → return the result.

Limits: Raw PowerShell flow steps and the setup actions system.config.toggleAgent and system.config.enterAgentPriorityMode are not supported through these structured tools. Normal natural-language setup remains available.

@GeorgeNgMsft
George Ng (GeorgeNgMsft) added this pull request to stack #2994 September 11, 2026 07:20
@GeorgeNgMsft George Ng (GeorgeNgMsft) changed the title Add thin structured-action adapters with explicit resumable conversation binding [3/3] Add thin structured-action adapters with explicit resumable conversation binding Sep 11, 2026
@GeorgeNgMsft
George Ng (GeorgeNgMsft) force-pushed the georgengmsft-structured-action-adapters branch from d57e19e to 89c495c Compare September 19, 2026 00:36
Base automatically changed from georgengmsft-guarded-action-execution to main September 19, 2026 01:46
@GeorgeNgMsft George Ng (GeorgeNgMsft) changed the title [3/3] Add thin structured-action adapters with explicit resumable conversation binding [3/3] Update Copilot plugin to leverage new TypeAgent MCP tools Sep 19, 2026
@GeorgeNgMsft
George Ng (GeorgeNgMsft) marked this pull request as ready for review September 19, 2026 03:13
Rio Yu (rioyu123) pushed a commit to rioyu123/TypeAgent that referenced this pull request Sep 19, 2026
This PR adds a safe way for clients to run a specific TypeAgent action
using structured input. It uses the dispatcher’s existing queue and
action engine, asks the user before making changes, pauses when the
action needs more information, and returns the action’s real result. It
also lets the same conversation reconnect to unfinished work without
allowing another client to take control.

## Where this fits

This is layer 2 of the structured-action stack:

1. microsoft#2991 lets clients search for actions and inspect their input
contracts.
2. **This PR safely runs the selected action and manages its
lifecycle.**
3. microsoft#2993 exposes the feature through MCP and Direct Action adapters.

microsoft#2991 has merged, so this draft now targets `main`. Native stack #2994
still tracks `[2991, 2992, 2993]`.

## What changed

- Add `executeAction`, `continueAction`, and `cancelAction` to the
public dispatcher API and dispatcher RPC.
- Run typed actions through the existing dispatcher queue and
`executeActions` engine. The implementation does not turn parameters
back into command text or send them through natural-language
interpretation.
- Look up the requested action by its exact `schemaName` and
`actionName`. Search ranking is only used to help clients discover
actions; it never decides which action is executed.
- Recheck the current scope, permissions, enabled state, readiness,
input schema, parameters, and safety policy before the action starts and
again after waits.
- Ask for confirmation unless the action is explicitly marked read-only.
A read-only action can still require confirmation, and a caller cannot
bypass confirmation by claiming that it already has approval.
- Pause and resume the same operation when an action asks a question,
shows a form, proposes an edit, or requests a choice. Continuing an
operation does not run the action again.
- Cancel structured operations without choosing a default answer. This
public `cancelAction` is separate from the existing internal agent-RPC
cancellation message: it checks the conversation scope and returns a
structured result.
- Return clear outcomes: `completed`, `failed`, `cancelled`,
`requires_interaction`, `unavailable`, or `execution_uncertain`.
Completed operations include the real action output, values, and
entities.
- Guard child actions and flow steps separately while allowing them to
use results created earlier in the same operation. The operation does
not silently reuse context from an earlier conversation turn.
- Add an opt-in reconnect token for structured actions. The token
belongs to one conversation and stays in memory. A reconnect takes
ownership from the old connection, while stale or unrelated clients are
rejected.
- Clean up cancelled SDK choices across in-process and agent-RPC
execution without changing normal chat behavior.
- Fix a Jest ESM issue where `signal-exit` could change the exported
shape of `process` while tests were loading.

## API flow

First, the client joins a conversation and opts into structured actions:

```ts
const joined = await joinConversation(io, {
    conversationId,
    structuredActions: {},
});

const resumeToken = joined.structuredActions.resumeToken;
```

The client searches for an action through the API added in microsoft#2991,
chooses one exact contract, and sends concrete parameters:

```ts
const search = await dispatcher.searchActions({ query: "save this item" });

const result = await dispatcher.executeAction({
    protocolVersion: 1,
    scopeId: search.scopeId,
    schemaName: "items",
    actionName: "save",
    parameters: { value: "example" },
});
```

If the action needs confirmation or another answer, it returns
`requires_interaction`. The client sends the answer back to the same
operation:

```ts
await dispatcher.continueAction({
    protocolVersion: 1,
    scopeId: result.scopeId,
    operationId: result.operationId,
    interactionId: result.interactionId,
    response: { type: "confirmation", approved: true },
});
```

Cancellation uses the same `scopeId` and `operationId`. If the client
disconnects, it can rejoin the same conversation with the resume token
instead of starting the action again.

There is no contract fingerprint or `contract_stale` result. The
dispatcher checks the current action definition and validates the
current parameters each time it reaches an execution boundary. If the
action was removed or disabled, it is unavailable. If its current input
schema no longer accepts the parameters, execution fails before entering
the handler.

## State limits

To keep memory use bounded, each dispatcher context keeps at most 100
live operations. Operations and interactions expire after 10 minutes,
and the latest 100 finished results are retained for 10 minutes. The
server keeps at most 100 structured-action conversation bindings, which
expire after 30 minutes without use.

## Validation

- Built dispatcher types, dispatcher RPC, dispatcher, agent SDK, agent
RPC, and the agent-server protocol, client, and server.
- Passed the full dispatcher test run: 132 suites and 2,113 tests, with
one pre-existing skip.
- Passed 87 structured execution and discovery tests together.
- Passed 63 focused RPC, SDK cancellation, reconnect, and server/host
tests.
- Passed the complexity, lint, test-debt, and circular-dependency checks
with no new violations, skipped tests, or dependency cycles.

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve the shared Dispatcher contracts, user interactions and result envelopes across MCP, Direct mode and the native command consumer. Add offline protocol integration and lifecycle coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove obsolete contract lookup, fingerprints and stale-contract statuses. Preserve live guard failures, explicit binding and user interactions; exercise schema removal and current policy across native and MCP consumers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@GeorgeNgMsft
George Ng (GeorgeNgMsft) force-pushed the georgengmsft-structured-action-adapters branch from 1fce5f6 to e49b745 Compare September 21, 2026 08:54

@datduyng Dominic Nguyen (datduyng) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve since this is just restructuring code

Build and stage the plugin locally, start an isolated server, probe the real MCP binding, and launch a controlled interactive discovery session with owned-process cleanup.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Document how interactive Copilot discovery differs from the direct MCP smoke probe.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Include Fluid Build dependency tasks while retaining targeted incremental package selection. Cover the production build command with a regression test.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve exact arguments and interactive TTY handles, await the actual child, retain launch diagnostics, and isolate the waiting wrapper from parent Ctrl+C. Keep smoke mode noninteractive and provide --same-window fallback.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread ts/packages/copilot-plugin/scripts/test/discovery-e2e.spec.mjs Dismissed
@GeorgeNgMsft
George Ng (GeorgeNgMsft) added this pull request to the merge queue Sep 21, 2026
Any commits made after this event will not be merged.
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.

3 participants