Version

CopilotSurface

Showing a Copilot turn inside the connector's chat — the display that opens the moment a message is accepted, the repaints with the thinking, the tools and the answer so far, and the finished answer with its links, its follow-ups and its confirmation card.

Subscriby\Connector\Contracts\Ports\CopilotSurface. Bound by copilot.

The core drives the four calls in order, the first from the request that accepted the creator's message and the rest from the queue: begin() the moment the message is accepted, progress() about once a second while the model streams, then one finish() or one fail(). The whole state travels on every repaint, so a connector repaints rather than appends and a lost call costs nothing. What a display is (a streamed draft on a platform that has them, a message edited in place on one that does not) is yours, kept in a CopilotTurnHandle of scalars the core carries back unopened.

Methods

MethodCalled whenReceivesReturns
begin()Copilot::ask() or a confirming decide() accepted the message, in that request.CopilotTurnOpening: the thread, the thinking sentence, and the question when it was tapped rather than typed.CopilotTurnHandle
progress()The model streamed something new, at most about once a second, from the worker.The handle and a CopilotTurnProgress: the reasoning so far, the tools in words, the answer so far as Markdown and as canonical HTML.CopilotTurnHandle
finish()The turn ended with an answer.The handle and a CopilotTurnAnswer.void
fail()The turn ended without one.The handle and one sentence, in the creator's language.void

The handle

CopilotTurnHandle is array<string, scalar|null> behind get() and with(): a draft id, a message id, which of the two the turn is on, whatever you need to find the display again. The core never reads it and carries it across the queue, which is why it holds scalars only. progress() returns a handle because a display may move: a platform that refuses the draft mid-turn is answered with a plain message from then on, and the handle says so.

The answer

CopilotTurnAnswer carries the answer twice, as the Markdown the model wrote with the follow-up block already removed and as the canonical HTML subset every renderer takes; links, one MessageAction::url() per dashboard page the turn's work opens at, each a signed address that lands the creator in the dashboard signed in; suggestions, up to three follow-up requests in the creator's words, for buttons of your own that send them back through Copilot::ask() with showQuestion set; card, the CopilotPendingCard the turn paused on, every label translated (the title, the tool in words, one line per argument, the note about what confirming costs, the two button labels), whose actionId your two buttons carry to Copilot::decide(); changedSomething; and question, the tapped question to repeat above the answer, since the chat never showed it.

How Telegram does it

The platform bot opens a rich message draft with a <tg-thinking> block that reads "Subscriby Copilot is thinking…", repaints the same draft with the reasoning's tail, a line per tool and the answer in Rich Markdown as it arrives, and sends the answer as a rich message with the card's Confirm and Cancel, the links and the follow-ups as inline buttons; the follow-ups' words are parked in the chat's storage, because callback data has sixty-four bytes. A Bot API server without the two calls is answered with a plain message edited in place, the handle remembering which of the two the turn is on.

What the kit checks

No kit rule drives CopilotSurface, because a display needs a platform. The fake connector binds FakeCopilotSurface, which records every opening, repaint, answer and failure (assertOpenedFor(), assertFinishedFor(), assertNothingOpened()); drive the core's side against it and your platform's fake client against the port.

Open the display in the request

begin() runs inside the connector's own webhook request so the creator sees the Copilot thinking at once; keep it to one platform call and let the worker do the rest. A begin() that throws stops the turn before anything is charged.

How is this guide?

Last updated on

Version

On this page

Subscriby is a product
designed by you — for you.
No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request

For AI agents: llms.txt · llms-full.txt