Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Getting Started with AI for VLSI Engineers5
  • Just Enough AI: Models and Context15
  • Prompting13
  • Trust and Verification14
  • Using AI for Engineering Work17
  • Engineering Walkthroughs7
  • Practical Foundations for AI Workflows4
  • Engineering Data5
  • Retrieval-Augmented Generation6
  • Agents and Tool Use18
    • What an Agent Is
    • Tool Use and Structured Output
      • Describing Tools to a Model
      • Propose, Execute, Validate
      • Handling Malformed Calls
      • Idempotent and Side-Effecting Tools
      • Tool-Call Validator Lab
    • Planning, Memory and Stopping
    • Multi-Agent Patterns and When Not to Use Agents
  • Agent Design8
  • MCP and Skills6
  • Multi-Agent Design6
  • Practical Capstone6
  • Tokens, Cost and Latency12
  • Agentic Workflows for Chip Teams18
  • Interview and Judgment10
  • AI Skills: Full Course Index
  • Working with AI Glossary
  • Working with AI Cheatsheet
Loading lesson

‹Tool Use and Structured Output
  1. Topics
  2. AI Skills for VLSI Engineers
  3. Agents and Tool Use
  4. Tool Use and Structured Output
  5. Tool-Call Validator Lab

Tools, Workflows and Agents · Beginner to Intermediate

Tool-Call Validator Lab

A small Python validator for tool-call JSON with an eleven-case self-check suite.

On this page

    Validator shape

    The validator is a small function from call text to verdict. It returns ok or one named fault, and execution follows only ok.

    Input class

    Example

    Verdict

    Valid read

    read_register with addr 5.

    ok

    Valid write with extra key

    write_register with addr, data, plus tag.

    ok, extras allowed.

    Unknown name

    zap_register.

    unknown-tool

    Missing argument

    addr absent.

    missing-addr

    Wrong type

    data is "12".

    type-data

    Out of range

    addr is 16.

    range-addr

    Eleven-case suite

    The suite below fixes eleven calls: four accepted and seven rejected. The split keeps the census exact.

    plaintext
    1
    2
    3
    4
    11 fixed cases in the suite
    accept: 4 of 11
    reject: 7 of 11
    check: 4 + 7 = 11

    Validator program

    The program below is the full validator plus its suite, with scripted calls standing in for a model. Thirteen checks accept four calls and reject seven.

    In Python, bool is a subclass of int, so the type check compares exact types and rejects boolean values.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    TOOLS = {
        "read_register": {
            "required": ["addr"],
            "types": {"addr": int},
            "bounds": {"addr": (0, 15)},
        },
        "write_register": {
            "required": ["addr", "data"],
            "types": {"addr": int, "data": int},
            "bounds": {"addr": (0, 15), "data": (0, 255)},
        },
    }
    
    def validate(call):
        if not isinstance(call, dict):
            return "not-an-object"
        if "tool" not in call:
            return "missing-tool"
        if call["tool"] not in TOOLS:
            return "unknown-tool"
        args = call.get("arguments")
        if not isinstance(args, dict):
            return "bad-arguments"
        spec = TOOLS[call["tool"]]
        for key in spec["required"]:
            if key not in args:
                return "missing-" + key
        for key in spec["required"]:
            if type(args[key]) is not int:
                return "type-" + key
        for key in spec["required"]:
            lo, hi = spec["bounds"][key]
            if args[key] < lo or args[key] > hi:
                return "range-" + key
        return "ok"
    
    CASES = [
        ({"tool": "read_register", "arguments": {"addr": 5}}, "ok"),
        ({"tool": "write_register", "arguments": {"addr": 2, "data": 255}}, "ok"),
        ({"tool": "write_register", "arguments": {"addr": 2, "data": 1, "tag": "x"}}, "ok"),
        ({"tool": "read_register", "arguments": {"addr": 15}}, "ok"),
        ({"tool": "zap_register", "arguments": {"addr": 1}}, "unknown-tool"),
        ({"tool": "read_register", "arguments": {}}, "missing-addr"),
        ({"tool": "read_register", "arguments": {"addr": True}}, "type-addr"),
        ({"tool": "write_register", "arguments": {"addr": 2, "data": "12"}}, "type-data"),
        ({"tool": "read_register", "arguments": {"addr": 16}}, "range-addr"),
        ({"tool": "write_register", "arguments": {"addr": 2, "data": 256}}, "range-data"),
        ({"tool": "read_register", "arguments": [5]}, "bad-arguments"),
    ]
    
    bad = 0
    accepted = 0
    rejected = 0
    for call, want in CASES:
        got = validate(call)
        if got != want:
            bad += 1
        if got == "ok":
            accepted += 1
        else:
            rejected += 1
    if accepted != 4:
        bad += 1
    if rejected != 7:
        bad += 1
    
    if bad == 0:
        print("PASS: 13 validator checks accept 4 calls and reject 7 across 11 cases")
    else:
        print("FAIL: " + str(bad) + " of 13 validator checks went wrong")
        raise SystemExit(1)

    Common mistakes

    Common pitfall

    Testing only the calls the proposer gets right proves nothing. Most cases must be malformed, one per fault shape, so each rejection path runs.

    Interview

    Likely probes: the validator contract and the suite balance.

    • One function maps call text to ok or a named fault.

    • Suite rule: more malformed cases than valid ones, each naming its verdict.

    • Extras are allowed, so new keys never break old validators.

    Check yourself A new optional key tag appears in calls. Must the validator change?

    No. Unknown extra keys are allowed, so old checks keep passing while the schema grows.

    Check yourself The suite has nine valid calls and one malformed call. What is wrong?

    It barely exercises rejection. Flip the balance toward malformed cases, one per fault shape.

    Related topics

    • Describing tools to a model

    • Self-checking regression

    Previous

    96 / 173

    Next: Planning, Memory and Stopping

    Up next

    Up nextPlanning, Memory and Stopping

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Describing Tools to a Model
    • Propose, Execute, Validate
    • Handling Malformed Calls