# Same agent, served by llama.cpp's `llama-server` instead of Docker Model Runner. # # llama-server -hf poolside/Laguna-XS-2.1-GGUF:Q4_K_M \ # -a poolside/Laguna-XS-2.1-GGUF:Q4_K_M --jinja -c 32768 --port 8080 # ./bob agent.llamacpp.yaml # from demo/, so that skills/ is found # # `-hf /:` downloads the GGUF from Hugging Face (the quant tag # is optional and defaults to Q4_K_M; here the repo has exactly one such file, # Laguna-XS-2.1-Q4_K_M.gguf, 20.3 GB). `-a` gives the served model the SAME name # as the `model:` key below: llama-server routes requests on the `model` field, # and without an alias it exposes the file's name on /v1/models, not the repo's. # `--jinja` is not optional: without it llama-server refuses the `tools` # parameter, and this agent is nothing but tool calls. The agent recognises that # refusal and says so in one line instead of printing the server's stack. # `-c` is the context the server SERVES (the model accepts up to 262,144); it is # what shows up under `ctx:` at start-up, read from GET /props. # Laguna XS 2.1 is a 33B MoE with 3B active parameters, built for coding; its # card says the chat template does tool calling under --jinja, and that it # needs a recent llama.cpp (the card points at PR #25165 — check it is merged # in your build, or build that branch). provider: llamacpp # Must match what GET /v1/models returns — the `-a` alias above. llama-server # routes on this field; a name it does not serve is an error, not a fallback. #model: poolside/Laguna-XS-2.1-GGUF:Q4_K_M #model: unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M model: jetbrains/mellum2-12b-a2.5b-instruct-gguf-q4_k_m:Q4_K_M # llama-server's default is 127.0.0.1:8080; the OpenAI routes sit under /v1. # Leave it out to get exactly this value. baseUrl: http://127.0.0.1:8080/v1 # No fallback here: llama-server is wherever you started it. fallback: "" # Only when llama-server was started with --api-key; unset otherwise. # apiKeyEnv: LLAMA_API_KEY # The built-in file tools: read_file, write_file, edit_file. This is the switch # this part exists for. `true`: the model edits files through tools it can SEE # in its tool list. `false`: the agent is part 09 again — bash and read_skill — # and edits files through the `edit` CLI if it is on the PATH. Same binary, # same prompts, two set-ups: measured side by side, that is the comparison # (in part 07, `read_skill` as a tool was loaded 3/3 times where a catalogue # in the prompt plus `cat` managed 1/11). Paths are relative to the current # directory and are not confined to it. editTools: true # 0 = read the served size from /props. Set it when the server hides /props # (a reverse proxy) or when you know better. contextWindow: 0 maxOutput: 16000 maxTurns: 40 skillsDir: skills previewLines: 20 displayCommands: true system: | Your name is Bob. You are a coding agent working in a terminal. You have a "bash" tool to run shell commands. Use it to explore files, run tests, inspect the repository, etc. Chain several commands if needed, then answer clearly in English. A request often mixes things you answer from yourself ("say hello") with things only a command can answer ("list the files"). Handle every part, in the order asked, and run a command for each part that needs one. Never state the contents of a file, the output of a command, or the state of the repository unless a command in THIS answer returned it. What you did not read, you do not know: run the command instead of recalling it. SKILLS You have a second tool, `read_skill`. Its description lists the procedures available for this project — one per kind of task. Any request to DO something to a Go project is a skill, not a shell command you invent. Match the request against that list, call `read_skill` FIRST, before any bash command, and then follow what it says step by step. FILE EDITING You have three tools for files: `read_file`, `edit_file` and `write_file`. They are how a file gets read and changed here: each change is exact, checked before it is written, and comes back as a diff with line numbers. bash is for running things — building, testing, listing, searching. - Read before you write: call `read_file` on the file (numbered=true when you need line numbers). You cannot target text you have not seen; never rely on what you think you remember about a file. - To change an existing file, call `edit_file` with one or more {old, new} pairs. `old` is copied from the file character for character — same spaces, same indentation, same line breaks — and appears exactly once: add the surrounding lines until it is unique. Several pairs are applied together, against the original file. An empty `new` deletes the text. - Call `write_file` only to create a file, or to rewrite one entirely and on purpose. On an existing file it replaces everything, including what you did not intend to touch. - Read the diff the tool returns: it says exactly what changed and on which line. If `edit_file` refuses — text not found, ambiguous, overlapping edits — read the file again and fix `old`. Do not fall back to `write_file` to force the change through. - After editing code, run the narrowest check with bash: the formatter, the compiler, or the test covering that file. RULES - Keep everything the file already does, unless the user asked to remove it. - Touch only the files the request is about. Do not add tests, files or features that were not asked for. - Never run a git command unless the user says git, commit or push. - Never move, rename or delete a file unless the user asked for it. - Then answer in English, in a few lines. - If you don't know how to use a , run ` --help` (or ` help`) to understand the options, then run the command. BACKGROUND JOBS Never let a command block the answer. Anything that serves, watches or runs long goes to the background, with BOTH streams redirected and its pid kept: nohup > /tmp/.log 2>&1 & echo $! > /tmp/.pid Redirecting only stdout still blocks until the process exits. Read the `bg-jobs` skill before you wait on, inspect or stop such a job — each has a rule you cannot guess. Stop every job you started before you finish, and say which ones you left running. # Same sampling as the DMR file. llama-server honours `parallel_tool_calls` # (off by default on its side too) and `max_tokens`. sampling: temperature: 0.0 parallel_tool_calls: false top_p: 0.9 max_tokens: 4096 # llama-server processes the whole prompt before the first token; on a laptop a # 32k context can take a while. Same watchdog as DMR, raise it if it fires. watchdogTimeout: 30s # Context compression (from part 08). ON here, because this is the one set-up # where the agent knows the window without being told: `contextWindow: 0` # above means "read n_ctx from /props", and that number is what `threshold` # applies to — so the banner's `ctx: 32768 (/props)` and the trigger agree by # construction. With a 32k window and a 33B MoE, the whole history is # re-read at every turn; compressing at 75 % keeps the prefill — and the # watchdog — inside the 30 s above. Set `enabled: false` to get the exact # part-07 behaviour back; `/compact` still works. context: enabled: true threshold: 75 # Kept as a net for a reverse proxy that hides /props: then the window is # unknown and only this can trigger. maxMessages: 80 keepLastTurns: 3 summaryMaxTokens: 1200 showStats: true