| 💾 Saved. d722711 k33g 4h ago | 1 | # Agent settings. |
| 2 | # |
| 3 | # Every key is optional: what you leave out keeps its built-in default |
| 4 | # (see internal/config/config.go). Nothing here requires recompiling — |
| 5 | # `go run .` picks the file up at startup. |
| 6 | # |
| 7 | # Use another file with: AGENT_CONFIG=./fast.yaml go run . |
| 8 | |
| 9 | # Which server is behind the URL. Left out, it means `dmr`: every agent.yaml |
| 10 | # written before this key existed keeps working unchanged. `llamacpp` speaks |
| 11 | # the same OpenAI-compatible protocol, but with its own port, its own way of |
| 12 | # refusing tool calls (no --jinja) and its own words in error messages — the |
| 13 | # provider is what turns those into one useful line. See agent.llamacpp.yaml. |
| 14 | # AGENT_PROVIDER overrides this key for one run. |
| 15 | provider: dmr |
| 16 | |
| 17 | # The chat model, in the provider's own naming (DMR: `ai/…`, `hf.co/…`). It |
| 18 | # MUST be able to emit tool_calls, otherwise the agent never runs a single |
| 19 | # command. AGENT_MODEL overrides it. |
| 20 | model: huggingface.co/jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M |
| 21 | |
| 22 | # Endpoint. `baseUrl` is tried first; if it does not answer, `fallback` is used |
| 23 | # — handy from a container or a sandbox, where the host is reachable as |
| 24 | # host.docker.internal. Both are LEFT OUT here on purpose: each provider has its |
| 25 | # defaults, and an explicit value is always respected — so with DMR's URL |
| 26 | # written in this file, `AGENT_PROVIDER=llamacpp ./bob agent.yaml` still talked |
| 27 | # to port 12434. Leaving them out keeps the file provider-neutral. These are the |
| 28 | # values the `dmr` provider fills in: |
| 29 | # baseUrl: http://localhost:12434/engines/v1 |
| 30 | # fallback: http://host.docker.internal:12434/engines/v1 |
| 31 | # AGENT_BASE_URL — or, for dmr, the older DMR_BASE_URL — overrides both without |
| 32 | # probing. `fallback: ""` (an explicit empty string) disables the fallback. |
| 33 | |
| 34 | # The NAME of the environment variable holding the API key — never the key |
| 35 | # itself, so this file can be committed and shown on screen. DMR ignores the |
| 36 | # key, so nothing is needed here; llama-server checks one only when started |
| 37 | # with --api-key (default variable: LLAMA_API_KEY). |
| 38 | # apiKeyEnv: LLAMA_API_KEY |
| 39 | |
| 40 | # How many tokens the server actually serves. The model does not know this: |
| 41 | # it is what the operator started the server with (`llama-server -c 32768`, |
| 42 | # `docker model configure`). Shown at start-up next to its origin, because a |
| 43 | # number without an origin never gets corrected. 0 = ask the server |
| 44 | # (llama-server tells its n_ctx on /props), else "unknown". |
| 45 | contextWindow: 0 |
| 46 | |
| 47 | # Max number of characters a tool returns to the model. Context safeguard: |
| 48 | # beyond that, the output is truncated (beginning + end kept). |
| 49 | maxOutput: 16000 |
| 50 | |
| 51 | # Max number of model ↔ tools round trips for a single question. Raise it for |
| 52 | # tasks that need long chains of commands. |
| 53 | maxTurns: 40 |
| 54 | |
| 55 | # The built-in file tools: read_file, write_file, edit_file. This is the switch |
| 56 | # this part exists for. `true`: the model edits files through tools it can SEE |
| 57 | # in its tool list. `false`: the agent is part 09 again — bash and read_skill — |
| 58 | # and edits files through the `edit` CLI if it is on the PATH. Same binary, |
| 59 | # same prompts, two set-ups: measured side by side, that is the comparison |
| 60 | # (in part 07, `read_skill` as a tool was loaded 3/3 times where a catalogue |
| 61 | # in the prompt plus `cat` managed 1/11). Paths are relative to the current |
| 62 | # directory and are not confined to it. |
| 63 | editTools: true |
| 64 | |
| 65 | # Where the `read_skill` tool looks for its markdown procedures. The path is |
| 66 | # relative to the CURRENT DIRECTORY, so run the agent from the directory that |
| 67 | # holds skills/ — not from src/. When the directory has no *.md file, the tool |
| 68 | # is not declared at all. |
| 69 | skillsDir: skills |
| 70 | |
| 71 | # How many lines of a command's output are echoed to the terminal. "Show me |
| 72 | # that file" means show it: running `cat` is not displaying it. 0 disables it. |
| 73 | previewLines: 20 |
| 74 | |
| 75 | # The system prompt: what the agent is, and what it is allowed to do. |
| 76 | # This is the knob to play with — it is the shortest path to changing behaviour. |
| 77 | system: | |
| 78 | Your name is Bob. |
| 79 | You are a coding agent working in a terminal. |
| 80 | You have a "bash" tool to run shell commands. |
| 81 | Use it to explore files, run tests, inspect the repository, etc. |
| 82 | Chain several commands if needed, then answer clearly in English. |
| 83 | |
| 84 | A request often mixes things you answer from yourself ("say hello") with |
| 85 | things only a command can answer ("list the files"). Handle every part, in |
| 86 | the order asked, and run a command for each part that needs one. |
| 87 | Never state the contents of a file, the output of a command, or the state of |
| 88 | the repository unless a command in THIS answer returned it. What you did not |
| 89 | read, you do not know: run the command instead of recalling it. |
| 90 | |
| 91 | SKILLS |
| 92 | You have a second tool, `read_skill`. Its description lists the procedures |
| 93 | available for this project — one per kind of task. |
| 94 | |
| 95 | Any request to DO something to a Go project is a skill, not a shell command |
| 96 | you invent. Match the request against that list, call `read_skill` FIRST, |
| 97 | before any bash command, and then follow what it says step by step. |
| 98 | |
| 99 | FILE EDITING |
| 100 | You have three tools for files: `read_file`, `edit_file` and `write_file`. |
| 101 | They are how a file gets read and changed here: each change is exact, |
| 102 | checked before it is written, and comes back as a diff with line numbers. |
| 103 | bash is for running things — building, testing, listing, searching. |
| 104 | |
| 105 | - Read before you write: call `read_file` on the file (numbered=true when |
| 106 | you need line numbers). You cannot target text you have not seen; never |
| 107 | rely on what you think you remember about a file. |
| 108 | - To change an existing file, call `edit_file` with one or more {old, new} |
| 109 | pairs. `old` is copied from the file character for character — same |
| 110 | spaces, same indentation, same line breaks — and appears exactly once: |
| 111 | add the surrounding lines until it is unique. Several pairs are applied |
| 112 | together, against the original file. An empty `new` deletes the text. |
| 113 | - Call `write_file` only to create a file, or to rewrite one entirely and |
| 114 | on purpose. On an existing file it replaces everything, including what |
| 115 | you did not intend to touch. |
| 116 | - Read the diff the tool returns: it says exactly what changed and on which |
| 117 | line. If `edit_file` refuses — text not found, ambiguous, overlapping |
| 118 | edits — read the file again and fix `old`. Do not fall back to |
| 119 | `write_file` to force the change through. |
| 120 | - After editing code, run the narrowest check with bash: the formatter, the |
| 121 | compiler, or the test covering that file. |
| 122 | |
| 123 | RULES |
| 124 | - Keep everything the file already does, unless the user asked to remove it. |
| 125 | - Touch only the files the request is about. Do not add tests, files or |
| 126 | features that were not asked for. |
| 127 | - Never run a git command unless the user says git, commit or push. |
| 128 | - Never move, rename or delete a file unless the user asked for it. |
| 129 | - Then answer in English, in a few lines. |
| 130 | - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`) |
| 131 | to understand the options, then run the command. |
| 132 | |
| 133 | BACKGROUND JOBS |
| 134 | Never let a command block the answer. Anything that serves, watches or runs |
| 135 | long goes to the background, with BOTH streams redirected and its pid kept: |
| 136 | |
| 137 | nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid |
| 138 | |
| 139 | Redirecting only stdout still blocks until the process exits. Read the |
| 140 | `bg-jobs` skill before you wait on, inspect or stop such a job — each has a |
| 141 | rule you cannot guess. Stop every job you started before you finish, and say |
| 142 | which ones you left running. |
| 143 | |
| 144 | # Generation settings (OpenAI API keys). Low temperature for a coding agent: |
| 145 | # we want precise and reproducible answers, not creativity. |
| 146 | sampling: |
| 147 | temperature: 0.0 |
| 148 | # Une seule commande par tour. Sans ça, le modèle peut en demander |
| 149 | # plusieurs d'un coup : Genkit les exécute EN PARALLÈLE, dans le même |
| 150 | # répertoire, et on ne sait plus quelle sortie appartient à quelle |
| 151 | # commande. Pour le détecteur de boucle, c'est pire : deux appels du même |
| 152 | # tour s'enregistrent dans un ordre indéterminé, et « la même action deux |
| 153 | # fois de suite » perd son sens. Mettre `true` pour retrouver le |
| 154 | # comportement par défaut de l'API. |
| 155 | parallel_tool_calls: false |
| 156 | top_p: 0.9 |
| 157 | max_tokens: 4096 |
| 158 | |
| 159 | watchdogTimeout: 30s |
| 160 | |
| 161 | # Context compression, carried over from part 08 (its CONTEXT_WINDOW.md has the |
| 162 | # reasoning). OFF by default: with `enabled: false` the agent behaves exactly |
| 163 | # as before. Why it exists: nothing in the agent ever shortens the history — |
| 164 | # measured with the fake engine of part 03, the messages sent to the model grew |
| 165 | # 2 → 5 → 7 → 9 over four requests, and every `bash` output (up to maxOutput |
| 166 | # characters) and every skill read stays until /quit. On a local model the |
| 167 | # window is fixed at load time and the prefill runs on the laptop, so a long |
| 168 | # session first shows up as a false "[watchdog: connection hang]", then as an |
| 169 | # error from the server. |
| 170 | # |
| 171 | # The window it measures against is the top-level `contextWindow` above — ONE |
| 172 | # key for the banner and for the trigger, so the two cannot disagree. When |
| 173 | # that key is 0, the value the provider's probe learned from the server is |
| 174 | # used (llama-server tells its n_ctx on /props; DMR tells nothing). When both |
| 175 | # are unknown, only `maxMessages` can trigger, and the agent says so at |
| 176 | # start-up. |
| 177 | context: |
| 178 | enabled: false |
| 179 | |
| 180 | # Compress when the history reaches this share of the window. 75 leaves a |
| 181 | # quarter for the next question, the outputs of its turns and the answer — |
| 182 | # a single `bash` output can be maxOutput characters, about 4-5k tokens. |
| 183 | threshold: 75 |
| 184 | |
| 185 | # Fallback on the message count, for when the window is unknown or the |
| 186 | # estimate is off. One command costs 2 messages (call + response), so 80 is |
| 187 | # roughly 30 commands of history. |
| 188 | maxMessages: 80 |
| 189 | |
| 190 | # Question turns kept raw at the end. The recent turns are where the model |
| 191 | # works; summarising them makes it re-run what it just did. Three covers |
| 192 | # "do X", "now fix it", "and test it" — the usual shape of a demo. |
| 193 | keepLastTurns: 3 |
| 194 | |
| 195 | # max_tokens of the summary request. Seven sections of one line per item |
| 196 | # fit in far less; the cap stops a runaway model from filling the window it |
| 197 | # was asked to empty. |
| 198 | summaryMaxTokens: 1200 |
| 199 | |
| 200 | # Replaces the built-in summary prompt (08-context-compression/CONTEXT_WINDOW.md |
| 201 | # § 4.1) when set. Empty = built-in. |
| 202 | prompt: "" |
| 203 | |
| 204 | # One line after each compression: what was replaced, what was kept, |
| 205 | # tokens before → after. Worth showing on a screen, noise in a log. |
| 206 | showStats: true |
| 207 | |
| 208 | displayCommands: true |