DEV Community

Sam Novak
Sam Novak

Posted on

Call whoami first: your agent should not trust a cached tool catalog

There is a failure I have now watched three separate teams hit, and it always looks like a bug in the agent.

An agent connects to a tool server, does useful work for a week, and then one day starts producing confidently wrong actions. It calls a tool that no longer exists. It tries to transition something it is not allowed to transition. It reports success on a mutation that silently did nothing. Everyone goes looking for the regression in the model, or in the prompt, and the actual cause is that the agent was working from a catalog of tools and permissions it had cached at some point in the past.

The fix is one boring call at the start of every session, and it is worth understanding why it is not optional.

A token is a connection, not a role

Here is the thing people get wrong about tokens on a permissioned tool server. The token identifies which named connection is talking. It does not carry the caller's authority.

That sounds like a distinction without a difference until something changes on the other side. The person the connection belongs to gets moved to a different team. Their role changes. An admin turns off tool access at the workspace level. A permission that used to be granted is revoked.

In a system built correctly, the token keeps working as an identifier and the authority is resolved fresh on every call from the person's current membership, roles, and permissions. Which means the answer to "can I do this?" can be yes on Monday and no on Tuesday with nothing about the token having changed. Wagglet's MCP server is explicit about this: a token identifies a named connection, and it never overrides the same person's current membership, roles, or permissions. Team-level access is off by default, and disabling it later rejects every connection request immediately without deleting the connections.

If your agent cached a permission list at connection time, it is now confidently wrong about what it can do, and the only symptom you will see is a failed action it did not expect to fail.

Tool schemas move under you

The second half is the tool catalog. Any actively developed tool server adds tools, renames arguments, tightens validation, and deprecates things. That is normal and healthy.

What is not healthy is an agent whose idea of the available tools came from documentation, a blog post, or a previous session's transcript. A copied old catalog is not a source of truth. The live tools/list response is. This is the same discipline as not hardcoding an API response shape you saw once in a tutorial, except the failure is quieter, because a model will happily improvise a plausible call for a tool that no longer accepts that argument.

So: whoami first, then read, then act

The sequence that holds up:

1. Establish identity and authority. Call the server's whoami (or equivalent) and treat its team, identity, roles, and permissions as the authority for this session. Not your prompt's belief about who you are. Not last week's.

2. Fetch the live tool schemas. Use them, not a remembered list. If a tool you were planning to call is gone, that is information, not an error to work around.

3. Discover ids with bounded search, and page properly. Cursors exist because the population can be bigger than one response. An agent that reads the first page and reports a total is producing a confident number that is wrong.

4. Read the complete authorized record before you change it. Fetch the ticket or document, keep the returned record and its item revisions, and use those in the mutation. This is what makes concurrent edits safe instead of last-write-wins.

5. Use the matching lifecycle command, and give each intended mutation a fresh operation id. Reuse an operation id only when you are deliberately retrying the same intended change. This is the difference between a retry and a duplicate.

The full sequence with the actual tool names is in the Wagglet MCP workspace guide.

Why this is more than hygiene

There is a design point buried in this that is worth pulling out.

A permissioned tool interface is not a database with a chat wrapper. It keeps the product's own language and its own lifecycle rules, and it refuses actions that do not fit them. That refusal is the feature. An agent that could freely write any field would produce records that are structurally valid and semantically nonsense - a task marked delivered with no evidence, a review verdict with no reviewer.

Which is why "read current state, then use the explicit action for what you actually mean" is not ceremony. It is the thing that keeps an agent's output reviewable by a human afterwards. If you want the reasoning behind treating delivery, acceptance, merge, and deploy as four separate facts rather than one status field, that is the argument in the Wagglet workflow.

The one-line version

Do not let an agent start from what it remembers. Make it ask who it is, what it may do, and what tools exist - every session, out loud, before the first action. It costs one call. It saves the class of bug that looks like the model got worse and is actually your permissions changing underneath a cached answer.

Background on the surrounding handoff model: how Wagglet works.

Top comments (0)