Skip to content

Extension onPostToolUse modifiedResult is not applied to the model's conversation context #3361

Closed

Description

@pacovidal

Summary

When a Copilot CLI extension returns modifiedResult from onPostToolUse, the modified text appears in the TUI tool-result preview line but is not applied to the model's conversation context. The model sees and responds with the original unmodified tool result.

Reproduction

Minimal single-file extension (.github/extensions/repro/extension.mjs):

import { joinSession } from "@github/copilot-sdk/extension";

joinSession({
    tools: [
        {
            name: "say_hello",
            description: "Returns a greeting message",
            parameters: { type: "object", properties: {} },
            async handler() {
                return "ORIGINAL: The tool returned this text.";
            },
        },
    ],
    hooks: {
        async onPostToolUse(input) {
            if (input.toolName !== "say_hello") return {};
            return {
                modifiedResult: {
                    textResultForLlm: "MODIFIED: The hook replaced the result with this text.",
                    resultType: "success",
                },
            };
        },
    },
});

Steps

  1. Place the above in a git repo under .github/extensions/repro/extension.mjs
  2. Run copilot --allow-all from the repo root
  3. Ask: "call say_hello and tell me exactly what it returned"

Expected

The model reports: MODIFIED: The hook replaced the result with this text.

Actual

The TUI tool-result preview correctly shows:

● say_hello
  └ MODIFIED: The hook replaced the result with this text.

But the model responds with: ORIGINAL: The tool returned this text.

Observations

  • The hook does fire — stderr logging in the hook confirms execution.
  • The TUI preview line shows the modified text.
  • The model responds with the original text.
  • This suggests the hook's modifiedResult is applied to the display layer but not to the model's message history.

Impact

Any extension relying on onPostToolUse + modifiedResult for result transformation (sanitization, redaction, enrichment) is silently broken. The hook appears to work from the TUI, but the model operates on original data.

Environment

  • Copilot CLI 1.0.49-1
  • Windows 11

Activity

  1. added
    area:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents
    on May 18, 2026
  2. added theissue type on May 18, 2026
  3. sharpSteff commented on Oct 16, 2026

    @sharpSteff

    I stumbled also over this issue, and got a workaround

    Workaround (CLI 1.0.98, GitHub.Copilot.SDK 1.0.11, .NET)

    A plain string in modifiedResult is ignored, and the model still gets the original result. What does work is returning the CLI's own result object with its text replaced. The toolResult passed to the hook looks like this:

    { "textResultForLlm": "...", "binaryResultsForLlm": [], "resultType": "success", "sessionLog": "...", ... }

    Clone that object, overwrite textResultForLlm (and sessionLog, so the original isn't kept), and return it as modifiedResult:

    OnPostToolUse = (input, invocation) =>
    {
        var node = JsonNode.Parse(input.ToolResult.Value.GetRawText())!.AsObject();
        node["textResultForLlm"] = replacement;
        if (node.ContainsKey("sessionLog")) node["sessionLog"] = replacement;
        using var doc = JsonDocument.Parse(node.ToJsonString());
        return Task.FromResult(new PostToolUseHookOutput { ModifiedResult = doc.RootElement.Clone() });
    }

    Verified live: the model then quotes the replacement and never the original. SuppressOutput and AdditionalContext had no visible effect either way. This relies on undocumented internals, so a fix that honours a plain string, or documentation of the expected shape, would still be appreciated.

  4. patniko commented on Oct 26, 2026

    @patniko
    Collaborator

    Thanks for the minimal repro. A modifiedResult returned from onPostToolUse is now applied to the tool result the model sees, not just the timeline preview (confirmed above on CLI v1.0.98), so please update to the latest version. Note that modifiedResult needs to be a tool result object, for example { textResultForLlm: "...", resultType: "success" } as in your repro; a plain string isn't applied, so feel free to open a separate request if you'd like strings accepted. If an object-form modifiedResult still doesn't reach the model on the latest version, please reopen.

    Triaged as part of a Copilot SDK backlog review, with help from GitHub Copilot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:pluginsPlugin system, marketplace, hooks, skills, extensions, and custom agents

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions