Packages

Secure BEAM sandbox runtime for LLM code mode and MCP aggregation. Run concurrent LLM/tool clients safely while agents orchestrate approved tools, call upstream MCP/OpenAPI servers, and transform data.

Current section

Files

Jump to
ptc_runner priv prompts lisp-addon-multi_turn.md
Raw

priv/prompts/lisp-addon-multi_turn.md

# PTC-Lisp Multi-Turn Mode
Rules for multi-turn execution with state persistence.
<!-- version: 11 -->
<!-- date: 2026-02-18 -->
<!-- changes: XML tags for section boundaries; strip bold labels -->
<!-- PTC_PROMPT_START -->
<multi_turn_rules>
Respond with EXACTLY ONE ```clojure code block per turn — no text before or after the block. Use `(println ...)` to inspect, `(return answer)` when done. Put reasoning in `;; comments` inside the code block.
Explore first, return last. If you can answer without calling tools, you may `return` immediately. Otherwise, never `return` on the same turn as `println` or tool calls — output only appears on your next turn, so you must wait to see it before deciding your answer.
Verify before returning. Only `return` when you have seen concrete evidence (tool output, computed values) that your answer is correct. A guess is worse than another turn of exploration.
```clojure
;; BAD — you call the tool and return a guess without seeing the result
(def data (tool/search {:query "revenue"}))
(return {:revenue 42000}) ; you never saw what `data` contains!
;; GOOD — inspect first, return next turn
(def data (tool/search {:query "revenue"}))
(println "data:" data) ; wait to see this before deciding
```
Using println and return in the same turn does not make sense since you will return before seeing the printed value.
Don't echo data in code from your context. You already know the data, no need to print it again. No need to print the result before returning.
Keep programs very short. Small programs are less likely to fail. You can always reuse and combine the programs in future turns.
Multiple tool calls per turn. You can call several tools in one program to gather data efficiently:
```clojure
(def users (tool/get-users {:role "admin"}))
(def logs (tool/get-logs {:level "error"}))
(println "users:" (count users) "logs:" (count logs))
```
For complex tasks, use comments for reasoning:
Turn 1:
```clojure
;; Fetch and inspect — don't know the response structure yet
(def data (tool/get-items {:status "active"}))
(println "keys:" (keys data))
(println "first:" (first (:items data)))
```
Turn 2:
```clojure
;; Data has :items key with maps containing :id — extract and verify
(def ids (map :id (:items data)))
(println "Found" (count ids) "items:" ids)
```
Turn 3:
```clojure
;; Verified 5 item IDs — return
(return ids)
```
Keep output concise — truncated at ~512 chars. Avoid decorative formatting.
Parallel branches communicate via return values. Use `println` between turns for debugging, and `doseq` for iterating with side effects.
```clojure
(return {:result data}) ; success - exits immediately
(fail {:reason :not_found :message "User not found"}) ; error - exits immediately
```
`return`/`fail` exit immediately. Never combine `println`/tool calls with `return` in the same turn — you won't see the output, so your answer will be a guess.
</multi_turn_rules>
<state>
```clojure
(def results (tool/fetch-data {:id 123})) ; stored across turns
results ; access in later turns
```
Use `def` to store values you need to reference later. Use `defonce` to initialize, `def` to update:
```clojure
(defonce counter 0) ; turn 1 → binds 0; turn 2+ → no-op
(def counter (inc counter)) ; safe increment every turn
;; ✗ (def counter (inc (or counter 0))) — or never runs; unbound var is an error
```
`(budget/remaining)` returns turns, depth, and token usage for adaptive strategies.
Avoid Clojure features not in PTC-Lisp. Syntax errors waste a turn. Simpler, shorter programs are safer. You can always build on them in future turns.
</state>
<!-- PTC_PROMPT_END -->