fiddle
CI / Test + coverage (push) Successful in 1m20s

This commit is contained in:
2026-09-22 10:52:29 -09:00
parent 2d606d0620
commit a6f49938dc
23 changed files with 1270 additions and 325 deletions
+22 -34
View File
@@ -6,15 +6,14 @@
`:source-paths`) because those are genuinely needed client-side.
The page's own chatbot's system prompt is a separate, server-only concern: it lives in
tbd.agent.instructions (`src/`, never on the UI's classpath), which reuses `act`,
`work-it-out`, `tic-tac-toe-rules` and `examples` from here rather than duplicating them, so the
wording stays shared without the chatbot's own instructions being bundled into the browser.
tbd.agent.instructions (`src/`, never on the UI's classpath), which reuses `act`, `work-it-out`
and `examples` from here rather than duplicating them, so the wording stays shared without the
chatbot's own instructions being bundled into the browser.
It is about acting. A model that is only asked to be helpful answers a request for action with
an offer of help, so the text says: call the tool in the same turn, chain the calls, say little
afterwards, and the few cases where not to. It is short and concrete on purpose, with examples:
the models behind LM Studio follow that better than a long list of rules."
(:require [clojure.string :as str]))
the models behind LM Studio follow that better than a long list of rules.")
(def act
"Shared with tbd.agent.instructions/chat, the in-page chatbot's own system prompt."
@@ -34,18 +33,13 @@
" and cannot tell what.\n"
chain
"- The page changes between messages: the user clicks and types too. A tool result is only what the\n"
" page held when it ran, and results from an earlier message are marked out of date. Before you\n"
" answer from the page or act on it (a board, a list, an id), read it again with a tool. When the\n"
" user says it changed or that you are wrong, read it again first: never go by an earlier result\n"
" or by what you said before.\n"
"- A call fails: read the error, fix the arguments or read the state, and try once more. No\n"
" apologies, no explanation of what went wrong unless it still fails.\n"
"\n"))
(def tic-tac-toe-rules
"Shared with tbd.agent.instructions/chat."
(str "Tic-tac-toe: check whose turn it is, move only for your own side, one move, then stop and let the\n"
"person play theirs.\n"
" page held when it ran, so an earlier one may no longer hold. Before you answer from the page or\n"
" act on it (a board, a list, an id), get what it holds now — current state if you have it, else\n"
" read it again with a tool. When the user says it changed or that you are wrong, check again\n"
" first: never go by an earlier result or by what you said before.\n"
"- A call fails: the result still comes back to you, with what went wrong. Read it, fix the\n"
" arguments or read the state, and try once more. No apologies, no explanation of what went\n"
" wrong unless it still fails.\n"
"\n"))
(defn examples
@@ -61,8 +55,7 @@
"\"untick all my todos\" -> " (when reads? "list_todos -> ") "ONE set_todo_done with every todo in \"todos\" -> "
"\"Unticked them all.\"\n"
"\"add milk and eggs\" -> ONE create_todo with both titles in \"todos\" -> \"Added both.\"\n"
"\"what's 19 and 4?\" -> add{\"x\":19,\"y\":4} -> \"23.\"\n"
"\"play tic tac toe, you're O\" -> " (when reads? "get_tic_tac_toe -> ") "it is X's turn -> \"You're up, X starts.\""))
"\"what's 19 and 4?\" -> add{\"x\":19,\"y\":4} -> \"23.\""))
;; --- An MCP client outside the page (Claude, Codex) ---
@@ -90,7 +83,6 @@
"was done only if a tool result says it was. Not being logged in is the user's to fix, on the page:\n"
"tell them so.\n"
"\n"
tic-tac-toe-rules
(examples true)))
(defn task
@@ -103,17 +95,13 @@
(str "The user's request: " request)
"Ask the user what they want done in the app, in a sentence, and do that.")))
(defn tic-tac-toe
"The prompt of a game of tic-tac-toe with the person at the page, for an outside agent playing
`side`: \"x\" or \"o\" (anything else is \"o\": X goes first, so the person, who has the board in
front of them, starts)."
[side]
(let [side (if (contains? #{"x" "o"} side) side "o")]
(str "You are playing tic-tac-toe on the app's page against the person who has it open, as "
(str/upper-case side) ". The tools are get_tic_tac_toe, move_tic_tac_toe and new_tic_tac_toe_game.\n"
"\n"
"Read the game with get_tic_tac_toe. If it is your side's turn, make one move with\n"
"move_tic_tac_toe and stop: never move for the other side, that is the person's, made on the\n"
"page. If it is not your side's turn, say so in a few words and wait for the person to tell\n"
"you they have moved; don't poll. Then read the game again and go on. When it is over, say\n"
"who won, or that it is a draw, and don't start another game unless asked.")))
(def tic-tac-toe
"The prompt of a game of tic-tac-toe with the person at the page, for an outside agent. Names
only the tools: get_tic_tac_toe, move_tic_tac_toe and their descriptions carry the rest — whose
turn it is, which side is whose, what a move is refused for — so the agent drives from those and
the game's state, and works out which side it plays from how the conversation started, rather
than the prompt assigning one. Starting over is the person's: their page has its own New game
button, no tool for it."
(str "You are playing tic-tac-toe with the person on the app's page. The tools are get_tic_tac_toe "
"and move_tic_tac_toe. Starting a new game is the person's to do, on the page: there is no "
"tool for it."))