A string-typed document ID may still name content this invocation cannot read. An integer-typed result limit may still exceed the application’s budget. Primitive validation is necessary, but it does not answer either permission or semantic questions. Put those decisions in a policy layer that runs before the handler.
The free assistant has only two tools: search_notes and read_note. Search requires a nonblank query no longer than 120 code points and an integer limit from one through five. Reads require an exact ID in the trusted readable set. The model can request actions, but it cannot extend that set by explaining why it wants access.
Treat note IDs as opaque keys into an in-memory fixture. A path-looking value such as ../../etc/passwd is not a request to open a host path. If that exact string is absent from the readable set, it is denied. The tool API never translates IDs into arbitrary filesystem reads.
Search input is also data. A query can contain instruction-like words without gaining authority over the application. The later capstone searches only the already permitted notes; it does not search everything first and merely hide unauthorized results afterward.
readable_ids = {'public-1', 'public-2'}
for requested in ('public-1', 'private', '../../etc/passwd'):
print(requested, requested in readable_ids)Keep shape errors and permission errors distinct in this teaching contract. A missing id field is invalid_arguments; a well-formed but unlisted ID is denied. Unknown names return unknown_tool. These codes are an application choice. A real public API should separately review which distinctions it exposes, but none of the branches here grants an additional capability.
Bounds are inclusive and tested at both edges. A Boolean is not an integer limit, a blank query fails, and a 120-code-point query is accepted while 121 fails. Do not trim an ID into a different allowed identity or quietly coerce a numeric string into a larger allowed limit.
for limit in (True, 0, 1, 5, 6):
permitted = type(limit) is int and 1 <= limit <= 5
print(repr(limit), permitted)Test a public ID, an unknown/private ID, a path-looking ID, extra fields and both numeric boundaries. Then read the capstone’s search tool carefully: authorization must filter the candidate corpus before returning search results, counts or text. These deterministic policy tests establish this fixture’s behavior; a real system also needs authenticated identity, OS isolation and tests for its actual data stores.