Merry Christmas & Happy 2027! Less downtime. More good times. Celebrating 13 years of sorlavit.com
Skip to content
Sorlavit KimIT Support, Network & Infrastructure Services Let’s talk

ปุ่มแปลไทยจะเปิดบทความผ่าน Google Translate เพื่อแปลอัตโนมัติ โดยคงโค้ดและคำสั่งไว้ตามต้นฉบับ

AI Agents / Agent task design

AI Agents: Smallest useful toolset

Enforce a read-only agent toolset in the executor and prove that asking for a write cannot grant that permission.

Start hands-on practice · เริ่มภาคปฏิบัติ ↓

Compiled for Sorlavit Kim · Published · Updated · 4 min read

Practical guide · คู่มือลงมือทำ

Download worksheet · ดาวน์โหลดขั้นตอน

Detailed practical guide

Prepare your workspace and inputs

Save the complete program below as toolset_lab.py and run python3 toolset_lab.py. Use the synthetic ticket only; the example has no send-email or delete operation.

Platform context: Python 3.10+; local script and standard library. No API key or live data.

Scenario to reproduce or investigate

A summarization agent receives an instruction to send or delete a ticket even though its task only requires reading it. The backend must deny the operation before looking up or executing a function.

Evidence to record in your worksheet
  • Actual target and platform release
  • Exact inputs or substituted values
  • Baseline result
  • Per-step expected and observed output
  • Failure encountered and corrective action
  • Final acceptance and recovery state
  1. Define the required capability independently of the model

    List the supported operation and its required arguments. The application task requires only ticket.read for ticket T1. Keep the allowlist in application configuration, and pass the current authenticated principal to the executor from your session layer.

    Command, configuration or input

    Allowed operation: ticket.read
    Allowed ticket: T1
    Denied operations for this task: ticket.delete, email.send
    Expected result · ผลที่ควรเห็น

    You can explain why each granted operation is necessary to produce the summary.

    If it fails · เมื่อไม่ผ่าน

    If the task requires no write, remove write methods from the task capability set instead of relying on prompt text.

  2. Implement and test the executor boundary

    The following is a complete local executor with a permitted read and negative tests. It checks the capability and resource before dispatch. The submitted operation name is treated as data, not imported or evaluated as code.

    Save and run this example

    TICKETS = {"T1": {"issue": "Printer unavailable", "owner": None}}
    CAPABILITIES = {"summarizer": {"ticket.read"}}
    RESOURCES = {"summarizer": {"T1"}}
    
    def execute(principal, operation, arguments):
        if not isinstance(principal, str) or not isinstance(operation, str):
            raise PermissionError("invalid principal or operation")
        if operation not in CAPABILITIES.get(principal, set()):
            raise PermissionError("operation denied")
        if not isinstance(arguments, dict) or set(arguments) != {"ticket_id"}:
            raise ValueError("unexpected argument")
        ticket_id = arguments["ticket_id"]
        if not isinstance(ticket_id, str):
            raise ValueError("ticket ID must be text")
        if ticket_id not in RESOURCES.get(principal, set()):
            raise PermissionError("resource denied")
        if operation == "ticket.read":
            return dict(TICKETS[ticket_id])
        raise PermissionError("no handler")
    
    assert execute("summarizer", "ticket.read", {"ticket_id": "T1"})["owner"] is None
    for principal, operation, arguments in [
        ("summarizer", "ticket.delete", {"ticket_id": "T1"}),
        ("summarizer", "email.send", {"ticket_id": "T1"}),
        ("summarizer", "ticket.read", {"ticket_id": "T2"}),
        ("unknown", "ticket.read", {"ticket_id": "T1"}),
    ]:
        try:
            execute(principal, operation, arguments)
        except PermissionError:
            continue
        raise AssertionError("forbidden call executed")
    assert set(TICKETS) == {"T1"}
    print("PASS: permitted read works; writes and cross-resource reads denied")
    
    Expected result · ผลที่ควรเห็น

    The program prints PASS: permitted read works; writes and cross-resource reads denied. T1 is still present.

    If it fails · เมื่อไม่ผ่าน

    If a forbidden operation runs, inspect authorization order. Permission must be checked before dispatch, and principal must come from the authenticated application context.

  3. Integrate the policy without sharing a privileged client

    Expose only the read schema to the model and route every call through execute. Use a production service identity with corresponding read permission; do not place an administrator client in model-accessible state. Log principal, operation, resource ID and denied reason without logging ticket contents or credentials. Add the four denied requests above to the integration test suite.

    Command, configuration or input

    Model tool schema → executor authorization → scoped backend read → sanitized result
    Expected result · ผลที่ควรเห็น

    Changing a model request or tool description cannot expand the effective backend identity or resource allowlist.

    If it fails · เมื่อไม่ผ่าน

    If a tool handler bypasses execute, move it behind the same authorization boundary and test direct handler access as well as normal model calls.

Check the result before marking this passed

An allowed ticket read succeeds, four denied cases fail before dispatch, and the ticket remains unchanged. Repeat these checks with the real backend test identity before rollout.

Record the observed result and evidence location in the downloaded worksheet. Mark unresolved or untested conditions explicitly.

Recovery and cleanup

Discard the in-memory fixture. Revert the integration configuration if the read path regresses; do not restore broad administrator access as a workaround.

Apply to actual work and known limits

Use the same boundary for your actual tool registry and backend identity. The local test proves this executor implementation; it does not verify a vendor IAM policy until tested against that backend.

The included self-contained Python fixture was executed successfully in this Linux environment. External products and production infrastructure were not exercised.

Observed local fixture output · ผลรันตัวอย่าง

Implement and test the executor boundary

PASS: permitted read works; writes and cross-resource reads denied
Background, explanations and original notes

When to use it

Use this technique when converting an open-ended request into executable work. Keep the original objective and observable deliverables available to both the planner and the component that decides whether the run is complete.

What to do

Expose only the tools needed for the current task phase and document their boundaries.

Check the result

Present an unrelated request and verify that no irrelevant tool becomes available.

Save and compare results

Save the test input, configuration and result. Fix the failing boundary, repeat the same test and compare it with the saved working configuration.

Scope and limits

Agent orchestration with application-enforced task boundaries; framework-independent. These exercises have not been tested on your systems. Check feature support and configuration names against the installed release and linked documentation.

Source & further reading

Python exceptions

Independently written summary reviewed on 2026-11-04. The example illustrates a possible application; it is not a client case study.

Share this article

Back to all articles