“I don't have access to the add_rows tool”
A bot kept the narrow tool list of a job that failed while planning, and handed the work back. The fix, and an audit that gave every feature its bot tools.
Asked to add five rows to a Leads table, a Prospecting bot answered "I don't have access to the add_rows tool in this session", and handed the person the five rows to type in themselves. It had the tool. It was holding the wrong session.
The session that outlived its job
A delegated job plans before it works, and planning runs with a deliberately narrow list: propose_plan, recall_memory, search_history, describe_table and query_table, plus reading the web. Look, don't touch. When a plan is approved, the job lets that session go, and the work resumes the same conversation with every tool.
That hand-off was the only place the session was let go. This job failed while planning and never reached it, so its session stayed live in the thread with the planning list, and the next run there, an ordinary request to add rows, reused it. Replying under a routine's post did the same with the routine's list.
The check moved to where the session is reused
The fix is not a second release on the failure path. A live session now records the tool list it opened with, and a run that wants to reuse it compares lists first. If they differ, the session is closed and the same engine session resumes with the right tools: the conversation carries over, only the tools change. A session still serving another run is shared, as before.
Every reuse of something expensive (a session, a connection, a cache) has to check that what it was built with still matches what the caller needs. A cleanup on the happy path is a promise the unhappy path does not keep.
Never hand the job back
The second failure was the answer itself: a bot without a tool told the person to do the work. So the same day, every feature in the app was listed against the tools a bot has for it, and each gap got a decision.
- New tools.
upsert_rowsadds without duplicates, matching on a key column and ignoring case, spacing and how a web address is written. Bots can also read and post in channels they belong to, run their own routines, list the connectors they lack with the steps to connect them, and report their own spend. - Refusals say where to fix them. A table a bot cannot write names Tables → Leads → Bots, or the bot's profile. A table that is not shared still reads exactly like one that does not exist.
- Routine allowlists bring siblings. A routine learned from a run that used a table's row tools now gets
add_rows,upsert_rowsandupdate_rows, so a routine that only looked something up can write its result.delete_rowsis not a sibling. Look-ups pass any allowlist. - A narrower run says so. A bot's instructions name each family of tools it has and what it is for, and a run with fewer tools than usual is told what is missing and what the person can do.
Some things no tool does, by design: change anyone's access or approval policy, decide an approval, read a secret or a key, share the workspace, or touch billing. The bot is told so once, with where the person does each.
All of it is in 0.11.3, at /download.
All posts

