Connect by JBRH Open Connect

Tool calling

Tool calling is the mechanism by which a language model, which can only produce text, causes something to happen. The application publishes a list of named functions with typed arguments; the model returns a request to call one; the application runs it, validates everything, and hands the result back as more context. The model never touches the database, the mailbox or the phone line.

Status
Reference What this means
Audience
both, developer
In the app
#/home
Last verified
Product version
6.3.2

The exchange, in four moves#

  1. The application sends the conversation and a list of tool definitions — each a name, a description written for the model, and a schema for its arguments.
  2. The model replies with either prose or a structured request: this tool, these arguments. It is a request, not an instruction that has already run.
  3. The application decides whether to honour it, runs the real function, and captures the result — including the failure, if it failed.
  4. The result goes back into the conversation and the model continues, now able to see what actually happened rather than what it assumed would.

Two properties of that loop matter more than the syntax. The model's output is a *proposal*, so every safety decision belongs on the application's side of the boundary. And the result is fed back, so a tool that returns a bare true teaches the model nothing, while one that returns the identifier, the state and the reason lets the next turn be specific.

What a schema is actually for#

The obvious answer is validation, and that is the least of it. A tool schema does four jobs at once, and a schema written only for the first is the usual cause of a tool that gets called at the wrong moment.

Selection
The name and description are the only things the model reads when choosing. create_followup beats handle_task because a model picking between forty tools is matching intent to words.
Shape
Types and required fields stop a whole class of malformed call before any code runs. See JSON Schema.
Elicitation
A required argument the model does not have forces it to ask the person rather than invent one. Making a field optional is how a guess gets in.
Documentation
The same definitions are what an external client reads. A description written for a model is read by a developer too.

Does Connect use tool calling?#

Used, and it is the main way the Connect Assistant does anything. manager.py and manager_tools.py publish 66 tools. Roughly a third are read-only — find_anything, get_thread, customer_360, recall, list_followups, search_knowledge, data_query — and the rest write: remember, forget, send_email, approve_draft, reject_draft, create_prospect, create_followup, create_case, move_opportunity, create_file, data_update.

Two constraints on that set are worth stating because they are unusual. First, the Assistant's rights are narrower than a person's: it cannot set pricing and it cannot clear a do-not-contact entry, even when the person asking could do both. Authority is not inherited from whoever is typing. Second, the screen context handed to the model is checked against the database before it is trusted, so a stale panel cannot become the argument to a write.

The engine that reads mail is a different design and mostly does not use tool calls: it runs a fixed sequence — triage, ground, draft, decide — where the steps are known in advance. Tool calling earns its cost when the next step is genuinely unknown, which is the Assistant's situation and not the engine's.

What a tool must check before it acts#

  1. Resolve the workspace from the session, never from an argument.

    Result A model that supplies someone else's identifier gets nothing, because the query is already filtered by the workspace kernel and again by row-level security.

  2. Re-read the record the argument names.

    Result The tool acts on what is in the database now, not on what the conversation said ten turns ago.

  3. Apply the same permission the human path applies.

    Result Tools call the domain service that owns the record rather than reaching for the table — see why an agent's tools should call domain services.

  4. Return the outcome in full, including refusals.

    Result A refusal is a result the model can act on. Silence is one it will paper over.

Where it goes wrong#

  • Too many tools with overlapping names. Selection accuracy falls before capability does; two tools that both sound like 'update the record' produce a coin toss.
  • Arguments invented under pressure. A model asked to complete a task with a missing identifier will sometimes produce a plausible one. Required fields and a re-read at the boundary are the defence, not a better prompt.
  • Tools that hide their failure. A function returning success on a no-op leaves the model reporting completion for work that did not happen.
  • Irreversible actions with no confirmation. Anything that leaves the building — a send, a call — belongs behind autonomy, not behind a tool description that asks the model to be careful.

Questions#

Can the model call a tool the person could not call themselves?

No, and in Connect it is narrower still. Every tool runs under the session's own workspace and permissions, and the Assistant additionally has two capabilities withheld from it that a person retains: pricing, and clearing a do-not-contact entry. Those need a human hand on them.

How many tools is too many?

The limit is selection, not capacity. Once several tools could plausibly answer the same request, accuracy degrades no matter how the list is ordered. The fix is sharper names and descriptions, or collapsing near-duplicates into one tool with an explicit mode argument.

Is tool calling the same as an API integration?

It is a layer above one. The integration is the code that talks to Gmail or a carrier; the tool is the description that lets a model ask for it by name, plus the validation between the two. Removing the model leaves the integration intact.