Repository navigation
Add createCallback: an awakeable URL the agent can hand off and await - #38
Merged
Merged
Conversation
createCallback is a pending tool, a generic form of humanApproval. run creates a Restate awakeable and returns its ingress resolve/reject URLs, which the model hands to another agent, a remote job or a tool. complete races the awakeable against a durable timeout (1s to 24h); the posted body becomes the result, and a reject or timeout a failure. Restate's ingress completes the awakeable itself, so no handler of ours sits on the callback path. An awakeable cannot be looked up by ID, so run leaves its future in a turn-local context.callbacks map for complete; both phases run in the same turn invocation and run always replays first. CALLBACK_BASE_URL sets the ingress as callers reach it (default http://localhost:8080). Programs are told not to create callbacks, since a nested pending call completes inline and would hide the URL. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
createCallback, a pending tool that works like a generichumanApproval. The agent gets a URL to hand off: to another agent, to a remote job such as Claude Code running elsewhere, or as an argument to another tool. Later it receives whatever is POSTed to that URL, unless the timeout passes first.{"pending": true, "operationId": "...", "status": "waiting", "purpose": "...", "callbackId": "sign_1...", "resolveUrl": "{CALLBACK_BASE_URL}/restate/awakeables/{id}/resolve", "rejectUrl": "{CALLBACK_BASE_URL}/restate/awakeables/{id}/reject", "timeoutSeconds": 3600}rejectUrl, or the timeout passing, arrives as a failure.cancelOperationcancels the callback like any other pending operation.CALLBACK_BASE_URLsets the ingress address that callers reach. It defaults tohttp://localhost:8080.Example flow
The user asks the agent to have a remote Claude Code session fix a failing build and report back, waiting at most one hour.
Other endings of the same flow:
"tests still red"torejectUrl. The model is told that the callback for "remote build fix" reported a failure: tests still red.cancelOperation({operationId: "call_1"}).resolveUrlto a sub-agent withmessageSubAgent. The sub-agent does the work and POSTs its result withcurlfrom its sandbox.Design notes
context.callbacksmap for the waiting half. This is replay-safe because both halves run in the samedoTurninvocation and the half that creates the awakeable always replays first. The exception is documented intools-api.tsand the skill reference.resolveCallbackhandler that signals the turn, ashumanApprovaldoes. Awakeables won because they give one opaque URL that accepts any body, with no public handler and no extra Agent state.resolveCallbacktool. If the model passed a malformed ID toresolveAwakeable, the SDK would abort and retry the attempt forever. Other agents complete a callback by calling its URL instead.executeProgram. A pending call inside a program completes inline, so the program would never see the URL. The program tool's description says to create the callback with a direct call.Test plan
pnpm lint,pnpm buildtest/callback.test.mjscovers success plus replay, a rejected callback, and a timeout.restate-server(not done before merge): create a callback, thencurl -X POST <resolveUrl> -d '{"status":"done"}'🤖 Generated with Claude Code