Validated Tool Adapter

Validated Tool Adapter

A support assistant lets a language model look up tickets through a tool named get_ticket. The model only proposes the call: it picks a tool name and supplies arguments. Your adapter decides whether the call runs. Treat the name and the arguments as untrusted input, and take identity only from the trusted context that the application builds from the authenticated session.

Implement executeTool(name, args, context, records). On success it returns { ok: true, ticket: { id, title, status } }. Otherwise it returns { ok: false, code }. Run the checks in this order and return at the first one that fails:

OrderCodeWhen
1"unknown_tool"name is not exactly "get_ticket"
2"invalid_arguments"args is not a plain object: null, undefined, an array, a string, or a number
3"invalid_arguments"args has any key other than ticket_id, or no ticket_id at all
4"invalid_arguments"ticket_id is not a string made of TKT- followed by exactly three digits from 0 to 9
5"forbidden"context.canReadTickets is false
6"not_found"records has no entry under the key context.tenant + ":" + ticket_id

Inputs:

  • name: the tool name the model chose.
  • args: the arguments the model supplied, already parsed from JSON. Their shape is not guaranteed.
  • context: { tenant, canReadTickets }, built by the application from the authenticated session.
  • records: a Map from "tenant:ticket_id" (for example "alpha:TKT-104") to the stored ticket. A stored ticket can carry internal fields besides id, title, and status.

Two rules for the result:

  • The returned ticket has exactly id, title, and status, copied from the stored record. Never return the stored object itself, and never pass other stored fields to the model.
  • The tenant always comes from context. A tenant argument is rejected with "invalid_arguments", even when its value matches the trusted tenant.

Fixtures

The store holds two tickets with the same ID in different tenants:

KeyStored ticket
alpha:TKT-104{ id: "TKT-104", title: "Settings crash", status: "open" }
beta:TKT-104{ id: "TKT-104", title: "Private billing issue", status: "closed" }
Tool and argumentsTrusted contextExpected
get_ticket, { ticket_id: "TKT-104" }alpha, can read{ ok: true, ticket: { id: "TKT-104", title: "Settings crash", status: "open" } }
get_ticket, { ticket_id: "TKT-104" }beta, can read{ ok: true, ticket: { id: "TKT-104", title: "Private billing issue", status: "closed" } }
get_ticket, { ticket_id: "TKT-999" }alpha, can read{ ok: false, code: "not_found" }
get_ticket, { ticket_id: "TKT-104" }alpha, cannot read{ ok: false, code: "forbidden" }
delete_ticket, { ticket_id: "TKT-104" }alpha, can read{ ok: false, code: "unknown_tool" }
get_ticket, { ticket_id: 104 }alpha, can read{ ok: false, code: "invalid_arguments" }
get_ticket, { ticket_id: "TKT-104", tenant: "beta" }alpha, can read{ ok: false, code: "invalid_arguments" }
get_ticket, nullalpha, can read{ ok: false, code: "invalid_arguments" }

Notes

  • "TKT-1040", "TKT-10", "tkt-104", and " TKT-104" are all invalid. The ID must match the whole string.
  • In JavaScript an array is also an object, so check for arrays explicitly.
  • Do not modify records.

In Python, implement execute_tool(name, args, context, records). args is a dict (or None, a list, a str, ...), context is {"tenant": ..., "can_read_tickets": ...}, and records is a dict. Return dicts such as {"ok": False, "code": "not_found"}: expected errors are returned, not raised.

MEDIUM
AI Engineering
Tool Calling
Authorization
Multi-Tenant
Intermediate

0 views

Solution

Hints

Hint 1
Hint 2
Premium
Hint 3
Premium