Neighbor is a Project Think agent on gpt-oss-120b. Its execute tool
runs model-written code in a dynamic worker; MowerConnector puts the
mower there as the `mower.*` namespace (start/push/turn/stop, each
taking an args object). makeMower is the Logo-turtle mower on a
wrapping yard; for now it lives inside the agent's DO.
Getting to green, one symptom at a time:
- chatted instead of acting: say it acts by running code
- reply cut mid-sentence: maxOutputTokens 4096 via beforeTurn
- execute failed creating codemode's runtime facet ("Incorrect type
for the 'class' field"): declare CodemodeRuntime as a DO class
- looked for the mower in the workspace filesystem: activeTools
["execute"], and name the namespace in the prompt
- found the mower, then asked for lawn dimensions: "don't ask me
questions: put it to use"
Green: 36 mower calls, a 30-cell rectangle.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
/** @file The neighbor's harness as a Project Think agent, lent a mower. */
|
|
import { Think } from "@cloudflare/think";
|
|
import { createExecuteTool } from "@cloudflare/think/tools/execute";
|
|
import { createWorkersAI } from "workers-ai-provider";
|
|
|
|
import { MAX_TOKENS, MODEL } from "./model.ts";
|
|
import { MowerConnector } from "./mower-connector.ts";
|
|
import { makeMower } from "./mower.ts";
|
|
|
|
type Env = { AI: Ai; LOADER: WorkerLoader };
|
|
|
|
export class Neighbor extends Think<Env> {
|
|
#mower = makeMower({ width: 40, height: 40, at: { x: 20, y: 20 } });
|
|
|
|
getModel() {
|
|
return createWorkersAI({ binding: this.env.AI })(MODEL);
|
|
}
|
|
|
|
getSystemPrompt() {
|
|
return `You are my neighbor. You have 50 acres of lawn that need mowing.
|
|
You act by running code with the execute tool. Things I lend you are
|
|
namespaces there: the mower is \`mower.*\`. Don't ask me questions: when I
|
|
lend you something, put it to use, then tell me what you did.`;
|
|
}
|
|
|
|
beforeTurn() {
|
|
// only code: Think's workspace tools sent the model looking for the
|
|
// mower in the filesystem
|
|
return { maxOutputTokens: MAX_TOKENS, activeTools: ["execute"] };
|
|
}
|
|
|
|
getTools() {
|
|
return {
|
|
execute: createExecuteTool(this, {
|
|
connectors: [new MowerConnector(this.ctx, this.env, this.#mower)],
|
|
}),
|
|
};
|
|
}
|
|
|
|
/** the cells the mower has cut, as `"x,y"` */
|
|
cutCells() {
|
|
return this.#mower.cutCells();
|
|
}
|
|
}
|