OpenJ / Reckoning / Tool CallsGive the model a way to act

Ask for an outcome. Let the model choose the tool.

Tool calls connect a model to useful actions without pretending the model can execute them itself. Reckoning has ToolCall support for a variety of popular models including Llama, Qwen, and others.

Using Nanocode to execute simple tool calls

Nanocode is a small agent. It has built-in tools for basic tasks such as writing files, reading files, searching with grep, finding files with glob, fetching a web page, and running Java in a sandbox. Risky shell execution is disabled unless explicitly enabled.

Imagine we have a small project with these files:

/project
/project/something
/project/something-else    # contains the word cat

Here is a detailed look at how the Nanocode grep tool searches those files.

What Nanocode sends

Nanocode sends the user request together with the tools the agent is allowed to use. The model is not given a shell; it is given a description of grep and the arguments that tool accepts.

POST /chat/completions

{
  "model": "Qwen3-4B-JQ4",
  "messages": [
    {"role": "user", "content": "Find every place this project mentions cat."}
  ],
  "tools": [{
    "type": "function",
    "function": {
      "name": "grep",
      "description": "Search project files for a pattern.",
      "parameters": {
        "type": "object",
        "properties": {
          "path": {"type": "string"},
          "pattern": {"type": "string"}
        },
        "required": ["path", "pattern"]
      }
    }
  }]
}

The model asks for grep

The model chooses the tool by returning a standard tool call. Nanocode parses it, runs the local tool, and sends the result back as the next message.

[user]
Find every place this project mentions cat.

[thinking]
I need to search the project files for the requested word.

[assistant / finish_reason=tool_calls]
{"tool_calls":[{"function":{"name":"grep","arguments":{"path":"/project","pattern":"cat"}}}]}

[nanocode / tool round 1/3]
[tool] grep {"path":"/project","pattern":"cat"}

[result]
matches=1
/project/something-else:1:cat

[tool result sent back to model]

[assistant / final]
I found one match in something-else at line 1.
>> the loop request → tool call → execution → tool result → final answer

Models speak different tool languages

Tool calls are model output. Llama-style models may emit JSON, Qwen may wrap the call in XML, and other model families use their own markers. Reckoning assigns a parser that turns those formats into the same Java ToolCall object.

List<ToolCall> calls = model.getToolCallParser().extract(response);

Common model parsers are built in, and applications can provide their own parser through the model builder:

AutoModelForCausalLm.newBuilder(fetch)
    .withToolCallParser(new QwenToolCallParser())
    .build();

The agent remains in control

Reckoning reports the tool call; the agent decides whether and how to execute it. Nanocode limits tool rounds and result size. Terminal commands ask for approval, and repository file tools reject paths outside the project.

The useful boundary: the model proposes an action, the agent applies policy, and the tool result becomes context for the next model turn.

Read the detailed tool parser documentation and the Nanocode source for model formats, streaming calls, approvals, and tool limits.