Skip to content

Expose typed search, plan, and apply APIs in the Copilot SDK #2106

Description

@gokhanarkan

Summary

Expose the typed search, plan, and apply APIs through the Copilot SDK, so SDK consumers including the Copilot app get the same guarantees as the CLI.

Parent epic: https://github.com/github/copilot-ecosystem/issues/1230

Architectural context: https://github.com/github/copilot-ecosystem/issues/1235

Scope

  • Surface search, plan, and apply with types generated from the runtime contract rather than hand-mirrored, so they cannot drift.
  • Preserve handle semantics end to end: single use, time bound, instance scoped, with stale, replayed, and foreign distinguishable by the consumer.
  • Preserve typed errors as discriminated unions. Do not collapse them to messages or exceptions at the SDK boundary.
  • Carry authentication and the correlation identity.
  • Document that plan and apply are separate steps and that a host must present the plan before confirming. The SDK must not make it easy to build an auto-installer.
  • Version the surface so a client can negotiate rather than crash against an older runtime.

Out of scope

  • Any client UI.
  • A convenience wrapper that combines plan and apply into one call. That would defeat the review step by design.

Dependencies

Blocked on the runtime typed contract and the apply implementation. Blocks the app installation work.

Deadline: finalised by 31 August 2026. See the epic https://github.com/github/copilot-ecosystem/issues/1230 for the full schedule and scope position.

Unblocked, 28 July 2026

The typed contract landed in https://github.com/github/copilot-agent-runtime/pull/13734. The generated TypeScript types already exist, so this issue is now a matter of exposing them rather than designing them.

  • Expose catalog.search and mcp.planInstall with their generated types. The names are Catalog*, not AgentFinder*.
  • searchId round-trips: returned on a successful search, accepted on the plan request. An SDK consumer must be able to attribute an install to a search without reconstructing it.
  • CatalogAuthenticationRequiredError surfaces as a typed, narrowable variant so an integrator can render "sign in" without matching on a status code.
  • Do not add a device or user identifier to any request.

One trap worth knowing, because it already cost this PR a CI round trip. A ServerApi implementation may be synchronous or asynchronous, so the generated result type is TResult | Promise<TResult> and reading .kind without awaiting does not type-check. Vitest transpiles through esbuild and does not type check at all, so a green test run says nothing here. Run lint:types after the last file is written.

Prefer explicit narrowing guards on kind over toMatchObject for variant-specific fields. toMatchObject will happily accept a field no variant declares, which is exactly the assertion style that lets a contract bug through.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions