Running goose fully offline on a DGX Spark The open-source agent framework Goose, built at Block and now hosted by the Agentic AI Foundation under the Linux Foundation, can run entirely offline on an NVIDIA DGX Spark with 128 GB of unified memory, using a local Ollama runtime and a model that supports tool calling, with no cloud API calls. A hands-on test confirmed the setup works with zero network packets leaving the machine, proving that local-first agent workflows are feasible on a desk-sized, low-power device. A hands-on look at running a local-first agent on the NVIDIA DGX Spark: zero cloud calls, on a 128 GB box that fits on a desk. Almost every agent demo you see talks to a frontier model over a cloud API. It works, but it quietly assumes your code, your prompts, and your data are leaving the building. goose https://github.com/aaif-goose/goose , the open-source agent framework built at Block and now hosted by the Agentic AI Foundation https://aaif.io/ under the Linux Foundation, does not have to work that way. It is local-first: point it at a model running on your own hardware and the whole loop, reasoning, tool calls, file edits, shell commands, can run without a single packet leaving the machine. I wanted to test the strongest version of that claim. Take a real agent, point it at a model running locally, give it actual work to do, and then prove that nothing went to the cloud. The machine for the job is the NVIDIA DGX Spark: a GB10 Grace Blackwell box with 128 GB of unified memory that sits on a desk and draws less power than a space heater. Here is how it went. The setup in one picture goose talks only to a local Ollama runtime over loopback on a DGX Spark; no cloud API is involved. Three pieces, all on one box: Ollama is the model runtime. NVIDIA and Ollama partnered so it runs well on the Spark out of the box, and it exposes an OpenAI-compatible API on localhost:11434. goose is the agent. It plans, calls tools, edits files, and runs commands. Its Developer extension is what turns “chat” into “actually does things.” The model is whatever you load with Ollama, as long as it supports tool calling. That last requirement is not optional, and it is the thing people most often get wrong. The only network hop in the entire loop is the loopback interface between Goose and Ollama. We prove that at the end. First, meet the box Before trusting any benchmark, it is worth confirming what we are actually running on. The Spark is an ARM machine, so uname reports aarch64, and nvidia-smi confirms the GPU: a single NVIDIA GB10 on driver 580, CUDA 13. $ nvidia-smi GPU Index | Name | Persistence Mode | Bus ID | Display Active | Volatile Uncorr. ECC | Fan | Temp | Perf State | Power Usage / Cap | Memory Usage | GPU Util | Compute Mode | 0 | NVIDIA GB10 | On | 0000000F:01:00.0 | Off | N/A | N/A | 45°C | P8 | 4W / N/A | Not Supported | 0% | Default | One detail surprises people: the Memory-Usage column reads Not Supported. That is not a broken driver. The GB10 is a unified-memory design, so the GPU has no separate framebuffer to report. The CPU and GPU share one coherent pool of LPDDR5X, and you read it with an ordinary Linux tool: free -h The spec sheet says 128 GB; free reports what is left after firmware and OS overhead, as a single pool that both the CPU and the GB10 draw from: bash $ free -h total used free shared buff/cache available Mem: 121Gi 3.8Gi 116Gi 6.6Mi 2.8Gi 117Gi Swap: 15Gi 0B 15Gi That is 121 GB of usable unified memory. With nothing loaded it is almost entirely free, and loading qwen3.5:35b-a3b later takes only about 29 GB of it. This is the number that matters for “what model can I fit,” and it is why a desk-sized box can hold models that would never fit on a normal GPU. A model that can actually use tools Ollama is an easy docker-like way to run the open source models. A quick check of the version and the models already on disk: bash $ ollama -v ollama version is 0.30.10 $ ollama list NAME ID SIZE MODIFIED llama3.1:8b 46e0c10c039e 4.9 GB 5 weeks ago qwen3.5:0.8b-bf16 81a0b6550a2d 1.8 GB 7 weeks ago gemma4:26b 5571076f3d70 17 GB 2 months ago gemma4:latest c6eb396dbd59 9.6 GB 2 months ago qwen2.5vl:7b 5ced39dfa4ba 6.0 GB 3 months ago nemotron-3-super:latest 95acc78b3ffd 86 GB 3 months ago qwen3.5:35b-a3b 3460ffeede54 23 GB 3 months ago Here is the catch that trips most people up: goose leans hard on tool calling, so the model must support it. A model without tool calling can only chat, which means disabling every extension and giving up the whole point of an agent. That requirement narrows the field. From the list above: qwen3.5:35b-a3b is the one I reached for. The Qwen3 lineage has excellent tool calling, and its mixture-of-experts design the a3b means only about 3B parameters are active per token keeps it fast despite being a 35B-class model. At 23 GB it leaves most of the Spark’s memory free. llama3.1:8b is a great lighter alternative. Llama 3.1 has native tool calling, and at under 5 GB the agent turns feel snappy. Don’t trust the model card, test it Model cards are optimistic. The honest check is to ask the model to call a tool through Ollama’s API and see whether it actually returns a tool calls field: curl -s http://localhost:11434/api/chat -d '{ "model": "qwen3.5:35b-a3b", "stream": false, "messages": {"role":"user","content":"What is the weather in Paris? Use the tool."} , "tools": {"type":"function","function":{ "name":"get weather", "description":"Get current weather for a city", "parameters":{"type":"object","properties":{"city":{"type":"string"}},"required": "city" } }} }' | jq '.message' The model came back with an empty content and a populated tool calls. It chose to call the tool, with the right function and the right argument: { "role": "assistant", "content": "", "thinking": "The user wants to know the weather in Paris and has specifically asked me to use a tool ... I should call the get weather function with \"Paris\" as the city parameter.", "tool calls": { "id": "call hsv7poun", "function": { "name": "get weather", "arguments": { "city": "Paris" } } } } That is exactly what an agent-capable model should do. If instead you get only plain text in content and no tool calls, that model cannot drive goose. Pick another and run the test again. While we are here, a quick look at raw decode speed. The –verbose flag makes Ollama print timing, including the eval rate in tokens per second: bash $ ollama run qwen3.5:35b-a3b --verbose "What is an AI agent? Answer in one sentence." An AI agent is an autonomous system powered by artificial intelligence that can perceive its environment, make reasoned decisions, and take independent actions to achieve specific goals without constant human intervention. total duration: 25.884s load duration: 8.914s prompt eval count: 20 token s prompt eval rate: 146.02 tokens/s eval count: 1283 token s eval duration: 16.830s eval rate: 76.23 tokens/s About 76 tokens per second of decode on a desk-sized box. ollama ps confirms where it ran and how much memory it took: bash $ ollama ps NAME ID SIZE PROCESSOR CONTEXT UNTIL qwen3.5:35b-a3b 3460ffeede54 29 GB 100% GPU 262144 4 minutes from now