Integration pattern

Why you should let the LLM call Hive, not call it yourself.


Recommendation. Expose Hive to your model as a tool it can choose to call. Do not bury MCP calls at fixed points in your own control flow. The wiring cost is similar; the result is not.

The two ways to wire it up

Most teams reach for the imperative version first, because it looks simpler:

# Imperative: your code decides, always, on every turn.
context = hive.search(user_question)        # always fires, relevant or not
answer  = llm(prompt=user_question, context=context)
return answer

The tool-calling version hands that judgement to the model:

# Tool-based: the model decides whether to search, what to search for,
# and whether what came back was worth a follow-up query.
tools = [
    {
        "name": "search_team_knowledge",
        "description": (
            "Search the team's knowledge base for prior decisions, standards "
            "and meeting outcomes. Use whenever the answer might depend on "
            "something the team already decided. Prefer this over guessing."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "question": {
                    "type": "string",
                    "description": "A natural-language question, not keywords.",
                }
            },
            "required": ["question"],
        },
    },
]
# ... on a tool_use block, call aiqbee_search and return the result.

Why the second one wins

1. Retrieval quality depends on the query, and the model writes better queries

aiqbee_search is semantic. Handed the user's raw words it does reasonably; handed a well-formed question it does considerably better. The model has the conversation in front of it — it can resolve "did we decide against that?" into "what was the decision on rate limiting the public API?" Your code cannot, because it does not know what "that" was.

2. Most turns should not search at all

"Thanks, that worked" needs no retrieval. An unconditional search burns latency and pushes irrelevant context into the prompt, which measurably degrades answers. Letting the model abstain is a feature, not laziness.

3. One search is often not enough

Real questions need a first search, a look at what came back, and a second, narrower search. That loop is native to tool calling and awkward to express in fixed control flow.

4. Writing back is where a memory layer earns its keep

This is the part most integrations skip, and it is the whole point. Give the model a write tool as well, and knowledge accumulates as a side effect of normal work instead of requiring someone to remember to file it.

{
    "name": "record_team_knowledge",
    "description": (
        "Record a durable decision, standard or outcome so it is available "
        "to the team later. Use when something is settled that a colleague "
        "would need in six months. Do NOT use for chit-chat, transient "
        "status, or anything you were not told."
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "title":   {"type": "string"},
            "content": {"type": "string",
                        "description": "Include who, what and WHY. Self-contained."},
            "type_id": {"type": "string",
                        "description": "A real id from aiqbee_get_neuron_types."},
        },
        "required": ["title", "content", "type_id"],
    },
}

Writing tool descriptions that work

The description is your actual integration surface — it is the prompt that decides whether the tool gets used correctly. A few things that consistently matter:

  • Say when to use it, not just what it does. "Searches the knowledge base" produces erratic use. "Use whenever the answer might depend on a prior team decision" produces good use.
  • Say when not to. Without an explicit exclusion, write tools get called on pleasantries and the brain fills with noise.
  • Name the shape of a good input. "A natural-language question, not keywords" changes what the model sends.
  • Return errors verbatim. Hive's errors are written to be actionable — a rejected duplicate returns the existing neuron so the model can update or link instead. Swallow that and you lose the recovery.

Guardrails worth keeping in your code

Handing the model judgement over when to call is not the same as handing it unrestricted authority. Keep these on your side:

  • Least privilege. Give the service account read-only access unless the agent genuinely needs to write. Access is per brain.
  • Separate identities per integration. One service account per agent, so audit history and revocation are meaningful.
  • Confirm destructive calls. Delete tools are best left out of the toolset entirely, or gated behind human approval.
  • Turn on audit for anything regulated — every write is then attributable to the calling service account. Paid feature; see Licensing & tiers.

When imperative calls are right

There is a legitimate case for calling directly: deterministic, non-conversational work. Bulk-importing documents, a nightly sync, a provisioning script, a migration. No judgement is required, so there is nothing to delegate — use the REST API or call the MCP tools directly and keep it simple.