Interview cheatsheet

Everything on one page. The TypeScript→Python map, the exact SDK shapes, the agent loop, and lines to say in the room.

TypeScript → Python, at a glance

TypeScriptPython
console.log(x)print(x)
// comment# comment
let x = 5 / const x = 5x = 5
\Hi ${name}``f"Hi {name}"
{ } blocksindentation (4 spaces) + :
=== / !==== / !=
&& / `
null / undefinedNone
true / falseTrue / False
x === nullx is None
arr.push(x)arr.append(x)
arr.lengthlen(arr)
arr.includes(x)x in arr
arr.map(f)[f(x) for x in arr]
arr.filter(p)[x for x in arr if p(x)]
obj.keyobj["key"]
obj.key ?? dobj.get("key", d)
Object.entries(o)o.items()
JSON.parse / JSON.stringifyjson.loads / json.dumps
function f(a: string) {}def f(a: str):
async function / awaitasync def / await
Promise.all([...])asyncio.gather(...)
try { } catch (e) { }try: ... except Exception as e: ...
throw new Error("x")raise ValueError("x")
x => x * 2lambda x: x * 2

Data structures

nums = [1, 2, 3]              # list  (array)
nums.append(4); nums[-1]     # push;  last element
nums[1:3]                    # slice indices 1,2

point = (10, 20)             # tuple (fixed-size)
x, y = point                 # unpack

msg = {"role": "user"}       # dict  (object / JSON)
msg["role"]; msg.get("k", 0) # access; safe default
for k, v in msg.items(): ... # iterate entries

names = {"ada", "grace"}     # set   (unique)

[n*2 for n in nums if n > 1] # comprehension = map + filter

Calling Claude (Anthropic Python SDK)

from anthropic import Anthropic

client = Anthropic()                    # reads ANTHROPIC_API_KEY

response = client.messages.create(
    model="claude-opus-4-8",            # default model
    max_tokens=1024,                    # REQUIRED — output cap
    system="You are concise.",          # system prompt is top-level, NOT a message
    messages=[
        {"role": "user", "content": "Explain agents in one line."},
    ],
    thinking={"type": "adaptive"},      # extended thinking on 4.6+ (no budget_tokens)
)

print(response.content[0].text)         # content is a LIST of blocks
print(response.stop_reason)             # "end_turn" | "tool_use" | "max_tokens" | ...

Stream long / high-max_tokens calls and grab the whole thing at the end:

with client.messages.stream(model="claude-opus-4-8", max_tokens=2048,
                            messages=messages) as stream:
    final = stream.get_final_message()

Model IDs: claude-opus-4-8 (default) · claude-sonnet-5 · claude-haiku-4-5 · claude-fable-5 (most capable).

Tools & the agent loop

A tool = a JSON-schema description (for the model) + a function (for you).

tools = [{
    "name": "get_weather",
    "description": "Get current weather for a city.",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
    },
}]

The loop — the single most important thing to be able to whiteboard:

messages = [{"role": "user", "content": "Weather in Paris?"}]

while True:
    resp = client.messages.create(
        model="claude-opus-4-8", max_tokens=1024,
        tools=tools, messages=messages,
    )

    if resp.stop_reason == "end_turn":
        print(resp.content[0].text)          # done
        break

    # 1) append the model's ENTIRE response
    messages.append({"role": "assistant", "content": resp.content})

    # 2) run each tool_use, collect a tool_result per call
    results = []
    for block in resp.content:
        if block.type == "tool_use":
            try:
                out = TOOLS[block.name](**block.input)   # your code runs
            except Exception as e:
                out = f"error: {e}"                       # never crash the loop
            results.append({
                "type": "tool_result",
                "tool_use_id": block.id,      # MUST match the tool_use id
                "content": str(out),
            })

    # 3) send all results back in ONE user message, then loop
    messages.append({"role": "user", "content": results})

Less boilerplate: @beta_tool + client.beta.messages.tool_runner(...) runs this exact loop for you.

Structured output (JSON you can trust)

from pydantic import BaseModel

class Person(BaseModel):
    name: str
    age: int

# messages.parse() validates the reply against the schema for you:
resp = client.messages.parse(
    model="claude-opus-4-8", max_tokens=1024,
    messages=[{"role": "user", "content": "Ada Lovelace, 36"}],
    output_config={"format": {"type": "json_schema", "schema": Person.model_json_schema()}},
)
person = resp.parsed_output          # a validated Person

Production guardrails

  • Cap turnsfor turn in range(max_turns), decide what happens if you hit it.
  • Catch tool exceptions — return the error as the tool_result; don't crash the loop.
  • Retry with backoff — wrap the model call; double the delay each attempt; give up after N.
  • Validate tool inputs — Pydantic on the model's arguments before any irreversible action.
  • Async when it helpsAsyncAnthropic + asyncio.gather to overlap independent I/O.

Say these out loud

  • "An agent is a loop: the model proposes an action, my code executes it, the result goes back, repeat until end_turn."
  • "Every tool_use needs exactly one tool_result with a matching tool_use_id, all in a single user message."
  • "max_tokens is required; system is a top-level arg, not a message; the reply is a list of content blocks."
  • "I cap turns, catch tool errors, retry the API call with exponential backoff, and validate arguments before side effects."
  • "Sync client for one-shots; AsyncAnthropic + gather to parallelize; stream long responses and read get_final_message()."