Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/gatekeeper-scheduler/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ export interface ScheduledTaskHook {
* runs through the restored Gadget and does not need the Scheduler binding.
*
* Every successful registration call creates a distinct hook; registration is not idempotent.
* `executeCode` ignores the exported function's return value, so print the schedule ID with
* `console.log()`. Empty console output is not evidence that registration failed, and the disabled
* hook appearing in Connections confirms success. Do not retry solely because no ID was printed.
* Return or print the schedule ID so it appears in the `executeCode` output. Empty output is not
* evidence that registration failed, and the disabled hook appearing in Connections confirms
* success. Do not retry solely because no ID was printed.
Comment on lines +283 to +285

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This text is weird. Why are we explaining the UI to the agent?

Did we actually have problems with agents getting confused and thinking that schedules had failed to be registered? If so, is the solution perhaps to simply emphasize that if the call doesn't throw, then the schedule has been registered?

Why does an agent care about the schedule ID at all? What can it do with this? Why are we telling it to log or return it?

@ndisidore ndisidore Aug 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The schedule id can be used by the agent to confirm the schedule exists via list()
Non-SOTA models would often get confused because they would call executeCode but to them nothing happened - it would just get a void output.
The would interpret this as a fail and attempt to re-register (often many times)

This is probably less important now that it won't be a void return, but returning the schedule id may still be useful so it knows how to check if it is still enabled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When you experienced this, were those non-SOTA models specifically trying to return the schedule ID? If so, maybe simply the fact that we're logging now will mean that they no longer get confused, without the need for this text?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Another thing we could do is: If the executeCode logs nothing, we could write "(function succeeded with no output)"

*
* @example
* // server.js
Expand All @@ -308,7 +308,7 @@ export interface ScheduledTaskHook {
* callback,
* { title: "Daily brief", description: "Prepare the morning activity summary." },
* );
* console.log("Schedule registered:", scheduleId);
* return scheduleId;
*/
export interface ScheduleSession {
/**
Expand Down
2 changes: 2 additions & 0 deletions packages/workshop-backend/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,8 @@ Note that this differs from the \`env\` a Gadget's own code sees: a Gadget's ser
When the user asks you to just do a task that can be done with these bindings, you should use executeCode to perform the task, instead of adding code to a gadget to do it.

The function also receives a \`self\` parameter which is a magic object that points back to this chat thread. Calling any method on \`self\`, like \`self.foo(123)\`, delivers a callback message to this chat and activates you to respond. \`self\` can be passed over RPC (e.g. to a subscription method) and stored in a Durable Object's KV storage for long-term callbacks. When an agent callback is received, it appears in your env under a name like \`PARAMS_1\`, with \`.args\` (the callback arguments), \`.resolve(value)\` (to return a value to the caller), and \`.reject(error)\` (to reject with an error).

A non-\`undefined\` value returned by the function is included as the final line of console output, so only return values that should be visible in this output.
Comment thread
maxwellpeterson marked this conversation as resolved.
Outdated
`.trim();

let LIST_CONNECTABLE_RESOURCES_TOOL_DESCRIPTION = `
Expand Down
3 changes: 2 additions & 1 deletion packages/workshop-backend/src/overseer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export default class extends WorkerEntrypoint {
}
}
}
await agent(self, env, this.ctx);
let result = await agent(self, env, this.ctx);
if (result !== undefined) console.log(result);
Comment thread
ndisidore marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we prefix this with some text explaining it is the return value of the function, to disambiguate from any logs appearing before that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added a "Return value: " prefix in d954141

}
}
`;
Expand Down
Loading