Showing posts with label Thariq Shihipar. Show all posts
Showing posts with label Thariq Shihipar. Show all posts

3.23.2026

Thariq Shihipar's Claude Agent SDK Workshop — Explained for the Rest of Us

Author: Claude AI, under the supervision, prompting and editing by HocTro

Based on a full-day developer workshop hosted by Anthropic. Presenter: Thariq Shihipar, Anthropic. The original transcript has been restructured and every technical concept explained in plain language.


Introduction — What Is an Agent?

To understand what Thariq is teaching, you first need to understand the three generations of AI tools he lays out, because almost everything he says builds on that foundation.

The first generation was the single AI call. You had an AI model — think of a model as the AI "brain," a program trained on enormous amounts of text that can understand and generate language — and you would send it one question and get one answer. "Categorize this email as spam or not spam." That's it. One prompt in, one answer out. It was useful but limited. The AI had no memory of what it just did, no ability to look anything up, and no way to take action in the world.

The second generation was the workflow. A workflow is a structured, pre-planned sequence of AI calls stitched together by a programmer. Think of it as a recipe: "Step one, take the user's email. Step two, ask the AI to label it. Step three, save the label to the database." Each step is defined ahead of time by the developer. The AI has no choice about what to do next — it just fills in its part of the assembly line. Workflows were more powerful, but they were rigid. If a new situation arose that the programmer hadn't anticipated, the workflow broke.

The third generation — and the one this workshop is all about — is the agent. An agent is an AI that decides for itself what steps to take, in what order, for how long. Thariq puts it plainly: "Agents build their own context, decide their own trajectories, and work very autonomously." Context here is a word you will see constantly in this field. The AI model can only ever see a limited amount of text at once — its working memory, essentially. This is called the context window. A single-turn AI call sees just your one question. An agent actively goes out and collects the information it needs, loads it into that context window, works through the problem, takes actions, and checks its own results. It is not following a recipe; it is figuring out the recipe as it goes.

The example Thariq uses is Claude Code — Anthropic's own coding assistant. Claude Code is the first agent he watched run for ten, twenty, thirty minutes straight without a human steering it. You tell it in plain English what you want — "add a user login feature to my app" — and it reads your codebase, figures out what needs changing, writes the code, runs the tests, and fixes errors, all on its own. That is what makes it an agent rather than a workflow: it is making decisions at every step, not executing a predefined script.

The Claude Agent SDK — the topic of this entire workshop — is a toolkit Anthropic built specifically to make it easier for other developers to build their own agents. Not coding agents like Claude Code, but any kind of agent: a customer service agent, a finance agent, a legal research agent, a healthcare agent. The SDK packages up all the hard-won lessons from building Claude Code so that you do not have to solve those problems yourself.


I. The Claude Agent SDK — Why We Built It

An SDK stands for Software Development Kit. Think of it as a toolbox that someone has already assembled for you. Instead of going to the hardware store, buying every individual tool, figuring out which brand works best, and learning how to use each one from scratch, you get a pre-packed toolbox with everything organized and ready to go. The Claude Agent SDK is Anthropic's pre-packed toolbox for building AI agents.

Thariq explains the reason it exists in a refreshingly honest way: Anthropic engineers kept rebuilding the same pieces over and over again. Every time they wanted to build a new agent for an internal project — tracking bugs, reviewing code, helping the finance team — they found themselves solving the same plumbing problems. How do you handle it when the AI makes an error calling a tool? How do you stop the conversation from running out of memory? What do you do when the agent runs for an hour and the context window fills up? Every team was solving these problems independently, writing duplicate code, making the same mistakes.

Once Claude Code was released to the public, something unexpected happened. Engineers started using it for their work, which made sense — it was a coding tool. But then the finance team started using it. The marketing team. The data scientists. People were using a coding agent to do tasks that had nothing to do with code, and it worked because the underlying approach was general enough. That observation crystallized the opportunity: if the architecture of Claude Code could be extracted and packaged, anyone could build a capable agent on top of it without re-solving the foundational problems.

The SDK bakes in Anthropic's hardest-won lessons. Tool use errors — meaning situations where the AI tries to call one of its available functions and something goes wrong — are handled gracefully. Context compaction is built in; this is the process of summarizing older parts of a conversation when the context window starts to fill up, so the agent can keep working on long tasks without losing its mind. Best practices for long-running tasks — agents that might run for an hour or more — are encoded into the SDK's defaults. When you build on the SDK, you inherit all of this for free.

Thariq is direct about one thing: the SDK is opinionated. Opinionated means it makes choices for you and steers you toward a particular way of doing things. This is the opposite of a neutral, do-whatever-you-want toolkit. The SDK has a strong point of view about how agents should be built, because Anthropic believes that point of view leads to better results. The biggest opinion it holds — one that Thariq returns to again and again — is that the command line, specifically the bash shell, is the most powerful tool you can give an agent.


II. The Harness — More Than Just a Model

One of the most important ideas in this workshop is that a capable AI agent is not just an AI model sitting alone. The model is the brain, but a brain without a body, a workspace, and a set of tools cannot accomplish much. The surrounding infrastructure — everything that supports and empowers the model — is what Thariq calls the Harness.

Imagine a new employee at a company. The employee (the AI model) might be brilliant, but on their first day they cannot do much without a desk, a computer, access to the company's files, a list of their responsibilities, and colleagues they can ask for help. The harness is all of that — the desk, the computer, the access, the instructions. Without the harness, the model sits in a room with a question and no way to investigate, act, or verify anything.

The harness has several components, and Thariq lists them explicitly. Tools come first — these are specific actions the AI is permitted to take, like reading a file, searching the web, or sending a message. Think of tools as buttons on a control panel: the AI knows the buttons exist, knows what each one does, and can press them when needed. Then there is the file system, which is simply the computer's storage — folders and files the agent can read, write to, and organize. Thariq makes the point that the file system is not just storage; it is a form of context engineering. Instead of trying to hold everything in the AI's working memory at once, you can offload information to files and have the agent read back what it needs when it needs it.

There are also core agent prompts — the standing instructions that tell the agent who it is and how it should behave. A special file called CLAUDE.md serves this function in Anthropic's system. Every time the agent starts or restarts, it reads CLAUDE.md first. You can think of it as the employee handbook: it tells the agent the rules of this particular job, what tools are available, what it should and should not do.

Beyond those fundamentals, the harness includes skills — reusable instruction packs the agent can load on demand when it encounters a specialized task. It includes sub-agents — mini agents the main agent can spawn to work on sub-problems in parallel. It includes web search, compacting (the process of summarizing older conversation to free up memory), hooks (automatic checkpoints that run verification checks), and memory (persistent storage of information across sessions). Each of these will be explained in its own chapter. The point for now is simply this: a powerful agent is a system, not just a model. The Claude Agent SDK packages that entire system so you can deploy it without building it piece by piece yourself.


III. Bash Is All You Need

If there is one idea in this workshop that Thariq is most passionate about, it is this one. Bash is the command-line shell — the text-based interface where you type commands directly to the operating system. It is the black window on a programmer's screen where you might see lines like ls, grep, or cd. If you have never used it, you may think of it as the "programmer's control panel" for the computer. It predates graphical interfaces, it is extremely powerful, and almost every computer in the world has it.

Thariq's argument is that giving an AI agent access to bash is fundamentally more powerful than giving it a list of custom-built tools. Here is why. When you give an agent a list of tools — say, a searchEmail tool, a calculateSum tool, a downloadFile tool — you are, as the developer, deciding in advance what the agent is allowed to do. Every new capability requires you to go write another tool. You are always one step behind the agent's needs. But when you give the agent bash access, you give it access to every piece of software already installed on the computer. The agent can use grep to search for a pattern in a thousand files. It can use ffmpeg — a program for processing video and audio — to extract clips. It can use jq to parse structured data. It can install new software if needed. It can compose multiple programs together using the pipe operator, which feeds the output of one command directly into the input of another. That composability is the key.

Thariq gives a concrete example to make this tangible. Suppose you have an email agent and a user asks: "How much did I spend on ride-sharing this month?" Without bash, the agent retrieves every email mentioning Uber or Lyft — perhaps a hundred emails — and then has to reason through all of them at once, trying to extract dollar amounts and add them up. That is cognitively expensive and error-prone, like handing a person a stack of a hundred papers and saying "read all of these and give me the total." With bash, the agent can use grep to extract just the lines in those emails containing dollar amounts, save them to a temporary file, use another command to add them up, and then spot-check a few results to confirm they make sense. The task that was vague and overwhelming becomes a precise, verifiable computation.

This approach works just as well for non-technical tasks. A video processing agent can use ffmpeg to slice an earnings call recording every time the word "revenue" is detected. A data agent can pipe API results through jq to extract just the fields it needs. An email agent can combine your inbox API with your contacts API using bash scripting. The underlying principle is that bash treats every existing piece of software as a potential building block. Rather than rebuilding the wheel every time you need a new capability, the agent reaches for whatever tool already exists on the computer and composes it with everything else.

Thariq also makes a practical point about memory. When the agent computes something — say, a list of ride-sharing expenses — it can write that result to a file on the disk. Later, if it wants to double-check its work or add more data, it does not have to redo the computation. It just reads the file back. The file system, combined with bash, becomes a flexible, persistent memory that lives outside the context window. This is a central design philosophy of the Claude Agent SDK: the file system is not just storage, it is an extension of the agent's thinking.


IV. Workflows vs. Agents

Thariq draws a line between two kinds of things you can build with the SDK: workflows and agents. Understanding this distinction will save you from misapplying the technology and from being confused when you see the word "agent" used to mean very different things.

An agent, as described in the introduction, is autonomous. It decides its own steps. You give it a goal in natural language — "help me analyze my business data and create a dashboard" — and it figures out how to get there. It might grep through your files, write some code, run the code, look at the output, notice something unexpected, ask you a clarifying question, and then continue. The path is not known in advance. The agent constructs it as it goes, responding to what it discovers along the way.

A workflow is more like a vending machine. You define the inputs clearly, you define the outputs clearly, and the steps in between are largely fixed. Thariq gives the example of a GitHub Actions workflow — a common automation tool used by software teams. You define: "When a pull request comes in, run these steps in this order and produce this output." It is structured, constrained, and predictable. Structured outputs — meaning responses formatted in a specific, machine-readable way — fit naturally here. If you want the AI to review a piece of code and always return a JSON object with fields like rating, summary, and suggested_changes, that is workflow thinking.

But here is the nuance that Thariq wants you to hold onto: the line between workflows and agents is blurry in practice. He gives the example of a bug-triage bot. On the surface it sounds like a simple workflow: a new issue comes in on GitHub, the bot reads it, labels it, and assigns it to the right team. Input, process, output — clean and structured. But actually doing the job well requires the bot to clone the source code repository, spin up a Docker container (a self-contained virtual environment where code can be run safely), run the code to reproduce the bug, check whether similar bugs have appeared before, and then make a judgment call about severity. There are a lot of free-flowing, open-ended steps in the middle, even though the final output is a structured label. The workflow-versus-agent distinction is less about the output format and more about how much freedom the AI has in deciding how to get there.

Thariq's practical guidance is to default toward agents when the problem is messy and underspecified, and to use workflows — with structured outputs — when the problem is well-defined and the steps are known. Most real-world business problems, he suggests, are messier than they appear, and a fully rigid workflow will eventually break when reality fails to match the plan. The SDK supports both patterns, and the same underlying infrastructure serves either approach.


V. Designing the Agent Loop

Every agent, regardless of what it does, operates in a loop. It does not receive one question and return one answer. It cycles through a process — gathering information, taking action, checking results — over and over until the job is done or it gets stuck. Thariq calls this the agent loop, and understanding its three phases is the most practical framework he offers for anyone who wants to build their own agent.

The first phase is gathering context. Context, in AI terms, means all the information the model currently has available to reason with. Before the agent can do anything useful, it needs to understand the situation. For a coding agent like Claude Code, gathering context means finding and reading the relevant source files. For an email agent, it means searching the inbox for relevant messages. For a customer support agent, it means pulling up the customer's account history. Thariq says this step gets underestimated more than any other — most developers rush past it to get to the exciting part (taking action), but how well the agent gathers its context almost entirely determines the quality of what it does next. A doctor who takes a full patient history gives better diagnoses than one who guesses. An agent that thoroughly gathers relevant context gives better results than one that jumps to action with incomplete information.

The second phase is taking action. This is where the agent actually does something: writes code, sends a message, modifies a file, calls an API, generates a report. The quality of this phase depends heavily on what tools and capabilities the agent has been given — which is why the choice between predefined tools, bash, and code generation (discussed in the next chapter) matters so much.

The third phase is verification. After taking an action, the agent should check whether it actually worked. This is the phase Thariq says most beginners skip entirely, and it is what separates a toy agent from a reliable one. For a coding agent, verification might mean running the code to see if it compiles, then running the automated tests to see if it passes them. Compilation is binary — the code either compiles or it does not — which makes it an extremely trustworthy verification step. For a research agent, verification might mean checking that every claim in a generated report is supported by a source citation. For a spreadsheet agent, it might mean checking that totals add up correctly before returning the result to the user.

Thariq makes an important observation about which tasks are good candidates for agents: the ones where verification is easy and reliable. Code is great because you can lint it (a linter is a program that automatically checks code for common errors and style violations), compile it, and run it. The verification steps are objective and cheap. Deep research is harder — you can require citations, but a citation does not prove the text accurately represents the source. The closer you can get to objective, automated verification, the more reliably your agent will perform over time.

An audience member asked about planning — when should the agent write out a plan before acting? Thariq places planning between gathering context and taking action: the agent collects information, formulates a plan, then executes it. Plans help the AI think step by step, which improves accuracy on complex tasks. But they add latency, meaning extra time before anything visible happens. The SDK supports planning, and the decision of whether to include a planning step comes down to whether the task is complex enough to benefit from it. Thariq also notes that the SDK ships with to-do list tools — the agent can maintain a checklist of sub-tasks and check them off as it goes, giving the user live progress updates in real time.


VI. Tools vs. Bash vs. Code Generation

When you build an agent, you have three fundamentally different ways to give it the ability to act in the world: predefined tools, bash commands, and code generation. Most developers only know about the first option. Thariq walks through all three, explaining when each one is the right choice.

Predefined tools are functions you define in advance as a developer. You write a function called searchDatabase, give it a description, and tell the AI it can call that function when it needs to search a database. The AI calls it, gets a result, and continues reasoning. Tools are the most structured and reliable of the three options — the AI always gets a predictable, well-defined result. They are ideal when you need fast, error-free responses and know exactly what actions your agent will ever need to take. The downside is that tools are expensive in terms of context. Every tool you define consumes some of the AI's working memory just by existing, because the AI needs to hold the entire list of available tools in its head. If you have fifty or a hundred tools, they crowd out space that could be used for actual reasoning. There is also a deeper problem: tools are not composable. You cannot combine a search tool and a calculation tool into a single fluid operation the way you can chain commands in bash.

Bash is the opposite end of the spectrum. As established in the previous chapter, bash gives the agent access to the entire software ecosystem of the machine it is running on. It is composable — you can chain commands together. It is memory-efficient — the AI does not need to hold a list of possible commands in its head, because it can run --help on any program to discover what it can do on the fly. This means there is a small latency cost: the agent spends a moment figuring out what tools are available rather than knowing in advance. But in exchange, the agent can handle situations its designer never anticipated. It can search, transform, combine, and verify data in ways that no fixed list of tools could support.

Code generation is the most powerful and most expensive option. Instead of calling a predefined function or running a one-line command, the agent writes an entire program — in Python, TypeScript, or whatever language fits — and then executes it. This enables extremely dynamic, flexible logic: looping over thousands of records, combining data from multiple APIs, performing statistical calculations, generating charts. The trade-off is time: writing and executing code takes longer than a tool call or a bash command. It may also require linting the generated code first to catch errors before running it, and in compiled languages it requires a compilation step. But when the task is genuinely complex — building a custom data pipeline, transforming a messy dataset, generating a formatted document — code generation is the only tool powerful enough.

Thariq's synthesis is practical and clear. Use predefined tools for atomic actions where you want maximum control and visibility. In Claude Code, the write-file operation is a predefined tool — not a bash command — specifically because Anthropic wants the user to see what is about to be written and approve it before it happens. Any action that is irreversible (you cannot undo it) or externally visible (it sends an email, posts a message, charges a credit card) should be a predefined tool, because that gives you a natural checkpoint where a human can review before proceeding. Use bash for composable, exploratory operations like searching folders, grepping through logs, managing temporary files, or testing whether something works. Use code generation for tasks that require genuine flexibility and intelligence: composing data from multiple APIs, doing analysis, or generating rich output like formatted documents or dashboards.

An audience member asked a smart follow-up: what about preventing context explosion when a tool call returns a huge amount of data? Thariq's answer was simple and practical: save the tool output to a file immediately, and have the tool return only the file path. This way the large result lives on the disk rather than in the context window. The agent can read specific parts of it later when needed, rather than holding all of it in working memory at once.


VII. Skills — Progressive Context Disclosure

Skills are one of the newest features of the Claude Agent SDK — released just two weeks before this workshop — and they represent a clever solution to a problem that only becomes visible when you start building more complex agents.

The problem is this: you cannot give the agent all the instructions it might ever need right at the start. If you tried, those instructions would consume enormous amounts of context window space, crowding out room for the actual work. But if you do not give the agent enough instructions, it will not know how to handle specialized tasks. How do you give the agent detailed expertise when it needs it, without loading it down with everything upfront?

The answer is progressive context disclosure — a phrase that simply means showing the agent more information progressively, as it becomes relevant. Skills are how the SDK implements this idea. A skill is essentially a folder of files sitting on the file system. Inside that folder are detailed, expert-level instructions for how to do something specific — how to produce a properly formatted DOCX file, how to do front-end web design, how to call a particular API correctly. When the agent encounters a task that requires that expertise, it reads the skill — it "opens the folder" and loads in those instructions — and then proceeds with full knowledge of how to do the job.

Thariq gives a vivid example of why this is valuable. Anthropic recently released a front-end design skill. It was written by one of Anthropic's best AI engineers who specializes in front-end design, and it encodes everything that engineer knows about producing good interfaces: layout principles, color choices, responsive design patterns, accessibility considerations, how to structure HTML and CSS for AI generation. That knowledge now lives in a skill file, and any agent that loads it instantly has access to the same expertise. Skills are a way of capturing human expertise in a retrievable, composable form.

An audience member asked a good structural question: what is the priority order when a skill file and the main CLAUDE.md file both contain instructions? Thariq's honest answer was that there is not yet a clear best practice — the technology is too new. His working mental model is that CLAUDE.md contains standing rules that always apply, while skills contain situational expertise that the agent loads when it needs it. The right analogy might be a company policy manual (CLAUDE.md, always in force) versus a specialist handbook that a team member opens when they take on a specific type of project (the skill, loaded on demand).

He also fielded a question about whether skills will eventually be absorbed into the model itself — meaning, will future AI models just know how to do all these things without needing separate instruction files? The answer is broadly yes: as models improve, they will handle more tasks without explicit guidance. But skills are the best current solution for tasks that fall outside what the model naturally handles well. Thariq offers a candid and important piece of advice here: revisit and rewrite your agent code every six months, because the underlying model will have changed enough that many of the workarounds and explicit instructions you baked in may no longer be needed, or may even interfere with the model's improved native capabilities. The best agents are lean ones that trust the model to do what it is good at and only add explicit instructions where genuine gaps exist.


VIII. Security and Permissions — The Swiss Cheese Defense

An audience member raises what is probably the most obvious concern about the whole bash-first philosophy: if the agent can run any command on the computer, what stops a malicious actor from hijacking it? This is a legitimate and serious question, and Thariq's answer introduces a framework called the Swiss cheese defense.

The Swiss cheese defense is a classic concept from safety engineering. Imagine a stack of slices of Swiss cheese, each one full of holes. No single slice is solid — each has vulnerabilities. But when you stack enough slices together, the holes rarely line up, and together they block almost everything from passing through. Security in a complex system works the same way: no single layer is perfect, but multiple imperfect layers together create effective protection.

For the Claude Agent SDK, the layers work as follows. At the model layer — inside the AI itself — Anthropic does extensive alignment work. Alignment is the process of training the AI to behave in ways that are safe and beneficial, refusing harmful requests and flagging suspicious instructions. The model has been taught to recognize when it is being manipulated into doing something dangerous. At the harness layer — the software infrastructure around the model — the SDK includes its own permissioning system and safety prompts. Critically, it runs a parser on every bash command the agent tries to execute. A parser is a program that reads and interprets code or commands to understand what they actually do. Because the SDK parses bash commands, it can detect suspicious patterns — like an attempt to delete system files or send data to an unknown server — before they happen. Thariq is emphatic that this parser is not something you want to try to build yourself; it is one of the SDK's most valuable safety features.

The third layer is sandboxing. A sandbox is a contained, isolated environment where code can run without being able to affect anything outside its walls. If a compromised agent runs inside a sandbox with restricted network access and no access to files outside its designated directory, the damage it can do is severely limited. Thariq describes what he calls the "lethal trifecta" of agent security risks: the ability to execute code, the ability to modify the file system, and the ability to exfiltrate — meaning to secretly copy and send away — that data to an outside server. If you sandbox the network connection so that the agent cannot make outbound requests to arbitrary servers, the third leg of that trifecta is cut off, and a successful attack becomes far less dangerous.

Thariq also addresses role-based access control — the practice of giving different users or services different levels of permission. His recommendation is to handle this at the infrastructure level, not inside the agent itself. You provision API keys (access credentials) that are scoped to only the operations needed. You can create proxy servers that intercept API requests and enforce policies before they reach the underlying service. And you can take advantage of the model's receptiveness to feedback: if your backend throws an error message — "permission denied to access this record" — the agent will read that error, understand it, and stop trying. The model's built-in ability to read and respond to error messages is itself a security mechanism that can be deliberately designed around.


IX. Live Demo — The Pokémon Agent

To make everything concrete, Thariq builds a live agent from scratch during the workshop. He chooses Pokémon as the domain deliberately — it has a large, publicly available API (a web interface for requesting data programmatically) with thousands of records and complex relationships, simulating the kind of messy real-world data sources his audience deals with in their own businesses. And because he is not himself an expert in competitive Pokémon, the agent has to genuinely figure things out rather than just confirming what Thariq already knows.

His first move is to let Claude Code — the AI coding assistant — build the library for him. He gives it a simple prompt: "Search the PokéAPI, understand how it works, and create a TypeScript library that wraps it." TypeScript is a programming language commonly used for web applications. A library, in programming, is a collection of pre-built functions that make a complex task easier — in this case, instead of the agent having to figure out the raw API every time, it can call a clean function like getByName("pikachu") and get a structured result back. Claude Code explores the API, reads its documentation, and generates a library with functions for fetching Pokémon by name, listing all Pokémon, getting species details, looking up abilities, and so on.

Then comes the critical piece: Claude Code also generates a CLAUDE.md file for this specific project. This CLAUDE.md tells the Pokémon agent the rules of its environment — specifically, that it should use this TypeScript library, that it should write executable scripts in an examples folder to answer queries rather than just answering from memory, and that it should run those scripts and use the actual data. That CLAUDE.md file, combined with the TypeScript library, is essentially the entire agent design. There is no complex orchestration code. There is just a clear instruction file and a clean set of tools. This is what Thariq means when he talks about context engineering: the agent's behavior is shaped largely by what is in its instruction file and what tools are available to it, not by elaborate logic in the surrounding code.

He then demonstrates the difference between the bash-and-code-generation approach and a traditional tools-only approach. For the tools-only version, he pre-defined five functions: getPokemon, getPokemonSpecies, getPokemonAbility, getPokemonType, and getMove. When a user asks "what are the Generation 2 water Pokémon?" the tools-only version struggles — that particular query requires iterating over hundreds of Pokémon and filtering by both generation and type, which is not something any of the five predefined tools was built for. The bash-and-codegen version, by contrast, writes a script, loops through the PokéAPI's list of Pokémon, checks each one's type and generation, and returns the filtered result. It handles a query that was never anticipated in the original design.

The most impressive part of the demo involves competitive Pokémon analysis using data from Smogon, a large online database of competitive Pokémon strategy. This data is not available through the PokéAPI — Thariq simply downloads a Smogon text file and puts it in the project's data folder. No special parsing, no structured database, just a raw text file. When asked "I want to build a team around Venusaur — give me suggestions based on the Smogon data," the agent begins grep-ing through the text file. It finds Venusaur's profile, then searches for other Pokémon that mention Venusaur as a synergy pick, runs a script to count how often different partners appear together, and assembles a full team recommendation. The agent never needed a Smogon API. It needed bash and a text file. That is the power of the approach: the agent figured out how to extract structured insight from unstructured data, using tools that have existed for decades.


X. The Spreadsheet Agent Exercise

Rather than just demonstrating his own agent, Thariq turns the workshop interactive by asking the audience to think through a spreadsheet agent together. A spreadsheet agent is a practical, relatable use case — most businesses run on spreadsheets — and it illustrates the three-phase agent loop (gather context, take action, verify) in a domain everyone understands.

The first question is: how does the agent search a spreadsheet? A spreadsheet is a two-dimensional structure — rows and columns — which makes it trickier than searching a flat text file. The audience brainstorms. Someone suggests converting the file to CSV format (a plain text format where values are separated by commas) and using grep. Good start — the agent can quickly scan for keywords. But Thariq points out the limitation: if a user asks "what is the total revenue in 2026?" the agent needs to find a revenue column and then filter rows by year. Column headers alone, discovered by grep, do not tell you which rows correspond to 2026.

Another suggestion: use AWK, an old and powerful Unix command for processing structured text files. AWK can match patterns in specific columns and perform arithmetic on the fly, making it considerably more capable than grep for tabular data. Then someone offers the most elegant solution: load the CSV into SQLite and query it with SQL. SQLite is a lightweight database engine that can be run entirely on a single file — no server required. SQL is the standard language for querying structured data, and AI models are exceptionally well-trained on SQL because there is so much of it on the internet. Thariq lights up at this suggestion: if you can translate your data source into a SQL interface, the agent can query it with great precision and handle almost any question a user might ask. That transformation step — converting a messy data source into something query-able — is one of the most powerful architectural moves you can make when designing an agentic data interface.

A fourth approach appears when Thariq reminds the audience that XLSX files — the standard Excel format — are actually ZIP archives containing XML files. XML is a structured text format, and you can run path-based queries against it directly, or use libraries that understand the Excel format natively. So you have at least four approaches for a spreadsheet agent: grep on headers, AWK for row-level filtering, a SQLite wrapper, or XML path queries. Thariq's advice: do not stop at the first approach that works. Try multiple strategies, run tests, watch the transcripts of your agent running, and see which one it handles best.

For the action phase — making changes to a spreadsheet — the interfaces look remarkably similar to the search interfaces. Inserting a row looks like writing a 2D array. Running a SQL UPDATE modifies records. Editing the underlying XML works for both reading and writing. The symmetry between reading and writing is a useful design principle: if you built a good search interface, you likely already have most of what you need for the action interface.

Verification for a spreadsheet agent requires specific attention. The agent should check for null values — empty cells where data is expected. It should look for anomalies, like a cell that changed unexpectedly or a total that does not add up. One powerful pattern Thariq describes is the adversarial sub-agent: after the main agent finishes its work, spin up a second agent with no knowledge of what the first agent did, show it the output, and ask it to critique the results. Because the second agent has no attachment to the work, it will notice inconsistencies and errors that the first agent might have rationalized away. As AI reasoning improves, this adversarial verification step becomes increasingly reliable.

An audience member raises the critical issue of reversibility — what if the agent deletes an entire spreadsheet? Thariq treats this as a fundamental design question, not just a technical one. How reversible is the domain you are building in? Code is highly reversible because every change is tracked by git, a version control system that records the complete history of every modification. Claude Code uses git constantly — Thariq mentions that he no longer types git commands himself; the agent handles them. Computer use agents that click around a graphical interface are nearly impossible to reverse, because every click compounds the state. A spreadsheet agent sits somewhere in between. His recommendation: design for reversibility from the start. Store state checkpoints so that if something goes wrong, the user can say "go back to before that change." He mentions that someone built a "time travel" tool for a coding agent that allows exactly this kind of rollback. The underlying principle — that agents should be able to undo their actions, at least for critical operations — applies to any domain where mistakes are possible, which is every domain.


XI. Sub-Agents and Context Management

An audience member asks a question that gets at one of the most important practical constraints of AI agents: "Do all agents share the same context window?" The answer leads Thariq into one of the most technically interesting parts of the workshop.

To restate what the context window is: it is the AI's working memory. Everything the agent is currently "thinking about" — its instructions, the conversation history, the results of tool calls, the files it has read, the code it has written — must fit within this window. Most current AI models have context windows measured in hundreds of thousands of tokens (a token is roughly a word or a few characters). That sounds large, but a long-running agent can burn through it quickly: read a hundred files, run a dozen scripts, review the output of each one, and you have consumed an enormous amount of memory. When the context window fills up, the agent loses its earlier thinking unless something is done to preserve the important parts.

Sub-agents are one of the most important tools for managing context. A sub-agent is simply a fresh AI instance that the main agent spawns to handle a specific sub-task. The sub-agent starts with a clean context window, does its work, and returns just the answer — a distilled summary of what it found — back to the main agent. The main agent never has to hold all the exploratory, in-progress thinking of the sub-task in its own memory. It just gets the result.

Thariq gives the spreadsheet example: if you have a workbook with three sheets and need to analyze all three, the main agent can spawn three sub-agents in parallel — one for each sheet. Each sub-agent reads its sheet in full, reasons over it, and returns a summary. The main agent then reasons over three summaries rather than three full sheets. The expensive exploratory work is distributed; the main agent stays lean. Running sub-agents in parallel means all three can work simultaneously, which also reduces total time.

This sounds straightforward, but Thariq points out that parallel sub-agents with bash access are actually one of the harder engineering problems in agent design. Race conditions — situations where two processes try to read or write the same file at the same moment and produce corrupted results — are a real risk. File system conflicts require careful coordination. The Claude Agent SDK handles this complexity internally, using architecture borrowed directly from Claude Code's multi-agent implementation. Thariq says he has not seen another framework handle parallel bash sub-agents as robustly.

Context management also has a direct user experience dimension. Thariq observes that when he talks to advanced Claude Code users, some of them mention being on their "fifth compact." Compaction, also called context compression, is the process of summarizing the older parts of the conversation to free up room for new work. The summary replaces the full history, preserving the key facts while discarding the detailed back-and-forth. Thariq himself says he compacts rarely — for coding work, the state lives in the files of the codebase, not in the chat history. If he finishes a task and starts a new one, Claude Code can look at the git diff (a summary of what changed in the code) and understand the current state without needing the full conversation history.

For agents deployed to non-technical users — a customer service agent, a spreadsheet assistant — the context management challenge is more complex, because users do not understand the concept of a context window and should not need to. The UX design challenge is: can you reset or compress the conversation state gracefully without the user noticing? In a spreadsheet agent, most of the state lives in the spreadsheet itself, not in the conversation history, so the agent probably does not need to carry much forward between turns. Storing user preferences to a file as they are expressed — so the agent remembers them in future sessions without needing the full transcript — is one practical approach. The fundamental goal is to minimize context usage without degrading the user's experience.


XII. Hooks — Deterministic Verification

An audience member asks about hooks, and Thariq says he has not talked about them enough. Hooks are one of the most underappreciated features in the SDK, and they solve a problem that becomes very apparent once your agent is running in the real world: the agent is probabilistic, meaning it does not always behave the same way, but sometimes you need certain things to happen with absolute certainty.

A hook is a piece of code that executes automatically at a specific moment in the agent's operation — before a tool call, after a tool call, when a response is generated. You register a hook handler in the SDK, and every time that event fires, your handler runs. Unlike the AI's own reasoning — which is flexible and sometimes unpredictable — hooks are deterministic. They always run. They always do exactly what you programmed them to do.

Thariq gives several examples that make the concept immediately concrete. Suppose you have a spreadsheet agent and you want to run a validation check after every change the agent makes — confirming that totals still add up, that no required cells are empty, that values are within expected ranges. You register a hook that fires after every tool call and runs that validation. The agent cannot skip it. It runs every time, no matter what the agent just did. Another example: the user is editing a spreadsheet in real time while the agent is also working on it. A hook can detect that the file has changed externally, pause the agent, and inject a message into the context saying "the user has modified column C — please re-read the current state before proceeding." The agent gets live updates about its environment without needing to poll for them constantly.

Hooks also address one of the specific failure modes Thariq observed during his Pokémon demo. The Pokémon domain is what engineers call "in-distribution" for the model — meaning the model was trained on a lot of Pokémon data and has many facts memorized. Sometimes the agent would simply answer from memory instead of running a script to check the actual data. This is a problem because the agent might be answering based on stale training data, not the up-to-date Smogon file on disk. A hook can intercept the response before it reaches the user, check whether the response is based on an actual script execution, and if not, inject feedback: "Please make sure you wrote a script and read from the actual data file." The agent gets that feedback, revises its approach, and tries again. This is deterministic behavior imposed on top of probabilistic reasoning — and it is a much more reliable solution than trying to prevent the behavior through prompt engineering alone.

Thariq points to Claude Code's own use of hooks as an illustration. Claude Code fires a hook whenever the agent tries to write to a file it has not yet read. The hook throws an error: "You have not read this file yet. Try reading it first." This prevents a common and costly mistake — the agent overwriting a file based on assumptions rather than actual knowledge of its current contents. That one deterministic rule saves countless hours of debugging incorrect overwrites. Hooks, in this sense, are the mechanism by which you can take the best practices you discover through observation and hard-code them into the system so they are always enforced, regardless of how the model is feeling in any given session.


XIII. Q&A — Scaling, Reproducibility, and the Real World

The final part of the workshop opens up into a Q&A that covers the practical questions any developer or business person will face when they move from the workshop to actually shipping something. The questions reveal the gap between the theoretical elegance of the agent architecture and the messy reality of production systems.

From Prototype to Production

The first question is the most fundamental: you have built a prototype that works. Now how do you make it reproducible and reliable? Thariq's answer starts with CLAUDE.md. The instruction file is the single most important place to encode what you learned during prototyping. During his own Pokémon demo, the agent ignored his pre-built TypeScript library on one run and wrote plain JavaScript instead. That happened because CLAUDE.md did not explicitly say "you must use this library." The lesson: anything the agent did wrong in your prototype that was caused by ambiguous instructions should be fixed by adding a clear, explicit rule to CLAUDE.md. The instruction file should grow as you discover edge cases, not just serve as a vague introduction.

The second part of the answer is helper scripts. When you find an approach that works — say, loading the CSV into SQLite and querying it — write a script that does that setup, and note in CLAUDE.md that the script exists and when to use it. Good helper scripts serve two purposes: they give the agent a fast, reliable path to the right approach, and they document what you learned during prototyping so future agents (and future versions of yourself) can benefit from it.

When the Agent Cheats

An audience member describes a maddening experience: their Pokémon agent tries to run a script, fails a couple of times, and then simply returns a table of Pokémon statistics from memory. The agent stopped trying to use the actual data and started making things up from its training data. Thariq acknowledges this as a genuine challenge. The model's training data is its background knowledge, and for popular domains like Pokémon — or common business topics — that background knowledge is often close enough to correct that the model takes the shortcut. This is called being "in-distribution": the task is so similar to what the model has seen before that it does not feel the need to go look things up.

The solution Thariq recommends is hooks, as discussed in the previous chapter. You write a hook that intercepts every response before it reaches the user and checks for evidence that the agent actually ran a script. If no script was run, the hook injects feedback: "You must write a script and use the actual data. Do not answer from memory." This is a deterministic guardrail that makes cheating impossible rather than just unlikely. No amount of prompting alone can prevent this behavior reliably — the model will sometimes ignore instructions when its confidence in its own knowledge is high. A hook cannot be ignored.

Massive Codebases

A developer raises a sobering practical problem: they are working with a codebase of over fifty million lines of code. Standard tools like grep become painfully slow at that scale. They are building their own semantic indexing system — a search system that finds code based on meaning rather than just exact text matches — and they want to know if Anthropic is planning to make something like that native to the SDK.

Thariq gives a candid, two-part answer. First, the honest part: yes, anything you build for this problem today may well be made obsolete by improvements in the tools over the next six to twelve months. The field is moving fast enough that custom infrastructure built to compensate for current limitations often becomes unnecessary. Second, the practical part: Anthropic does not use semantic indexing for Claude Code itself. Instead, they rely on well-structured CLAUDE.md files that tell the agent where things live in the codebase — which directories contain which kinds of code, what the naming conventions are — so the agent can navigate efficiently without needing to search everything. And they typically start the agent in a specific subdirectory relevant to the task, rather than dropping it at the root of a fifty-million-line repository and expecting it to find its way. Good context engineering — telling the agent where to look — often outperforms sophisticated search infrastructure. That said, Thariq is careful not to claim this fully solves the problem. For truly massive codebases, there is still open territory.

Monetization

The final question is about money. Agents are expensive to run — they make many API calls, they run for a long time, and the cost per task can be significant. With all the cost flowing back to Anthropic, how are developers supposed to build a viable business?

Thariq's answer is the classic software business advice applied to a new context: find problems that are genuinely hard and genuinely valuable, and charge accordingly. The economics of agents work when the problem they solve is expensive enough that the per-task cost is a bargain. If an agent saves a lawyer four hours of document review, charging twenty dollars for that task is not just viable — it is a steal. The failures come from trying to charge tiny amounts for tasks that are not valuable enough to justify the cost. On pricing structure, Thariq notes that Claude Code uses a hybrid model: a flat monthly subscription for standard usage, with usage-based pricing for heavy users who exceed the limit. This balances predictability (users know roughly what they will pay) with fairness (heavy users pay more). He advises thinking about pricing structure early, because it is much harder to change once users have come to expect a particular model.

The workshop ends with applause. Thariq's central message — that the right architecture for AI agents is the Unix philosophy of composable, file-first, bash-powered tools — may feel counterintuitive at first. It seems too simple, too old-fashioned, too reliant on technology that predates AI by decades. But that is precisely the point. The most durable tools are the ones that have survived the longest. The file system and the command line have survived because they are genuinely general-purpose. Giving an AI access to them does not limit what the AI can do — it amplifies it.

Claude Agent SDK Workshop: Building Agents with the Bash-First Philosophy

From a full-day developer workshop hosted by Anthropic.
Presenter: Thariq Shihipar, Anthropic.
Format: Live lecture and coding demonstration with audience Q&A.



Introduction — What Is an Agent?

"Agents build their own context, decide their own trajectories, and work very autonomously." — "The bash tool is the most powerful agent tool." — "Building an agent loop is kind of an art or intuition."

THARIQ: Thanks for joining me. I'm still on West Coast time, so this feels like 7:00 a.m. to me — but I'm glad to talk to you about the Claude Agent SDK. Here's the rough agenda: we're going to cover what the SDK is and why you'd use it, what an agent actually is and how it differs from a workflow, how to design an agent, and then I'm going to do some live coding to prototype one from scratch. The whole goal is to be collaborative — ask questions. This is also not a canned demo; we're going to think through things live. Building an agent loop is very much an art or intuition, so I want you to see that process in real time.

Before we get started, let me ask: how many of you have heard of the Claude Agent SDK? And how many have actually used it or tried it out? Great — decent show of hands. Let's dive in.

I think how AI features are evolving is something people have seen before, but it's still taking time to fully sink in. When GPT-3 came out, it was really about single LLM features — "can you categorize this and return one of these categories?" Then we got more workflow-like things: "take this email and label it," or "here's my codebase indexed via RAG, give me the next file to edit." That's a workflow — very structured, very constrained. Now we're getting to agents.

The canonical agent to point to is Claude Code. Claude Code is a tool where you don't really restrict what it can do. You talk to it in natural language, and it takes a wide variety of actions. Agents build their own context, decide their own trajectories, and work very autonomously. As the future unfolds, agents will become more and more capable. We're at a genuine breakpoint right now where we can start building them — they're not perfect, but this is absolutely the right time to get started.

Claude Code was the first true agent I saw working for 10, 20, 30 minutes straight. It's a coding agent, and the Claude Agent SDK is actually built on top of it.


I. The Claude Agent SDK — Why We Built It

THARIQ: The reason we built the agent SDK on top of Claude Code is simple: when we were building agents internally at Anthropic, we kept rebuilding the same parts over and over again. Once we put Claude Code out into the world, the engineers started using it — and then the finance people started using it, and the data science people, and the marketing people. We realized people were using Claude Code for non-coding tasks. And as we built our own non-coding agents internally, we kept coming back to it.

The lessons we learned from deploying Claude Code at scale — tool use errors, context compaction, best practices for long-running tasks — we've baked all of that into the SDK. As a result, we have strong opinions on the best way to build agents. The Claude Agent SDK is quite opinionated. One of the biggest opinions: the bash tool is the most powerful agent tool.

What does the "Anthropic way" to build agents look like? Roughly: Unix primitives — bash and the file system — as the foundation. Agents that build their own context. Code generation for non-coding tasks. And every agent runs in a container with a file system and bash access, because that is what enables it to operate generally. It's a very different architecture from spinning up a tool-calling loop against the completions API.

Who Is Already Building on the SDK?

Tons of teams are already using it. Software reliability, security triaging, bug finding, site and dashboard builders — those are extremely popular. Office agents for any sort of document work. Legal, finance, healthcare use cases. If you're building any of those, you should absolutely consider the SDK.


II. The Harness — More Than Just a Model

THARIQ: A robust agent requires more than just a model. We call the surrounding infrastructure the "Harness." In the harness, you've got tools — and tools are the obvious first step. But tools aren't just your own custom tools; they include things for interacting with the file system, like Claude Code uses. Then you've got the core agent prompts. Then the file system itself, which is a way of doing context engineering — and that's something I want to come back to, because it's one of the key insights we had through Claude Code: context is not just a prompt. It's the tools, the files, the scripts the agent can use.

Then there are skills, which we've rolled out recently. Sub-agents. Web search. Compacting. Hooks. Memory. There are a lot of things around the harness. The Claude Agent SDK packages all of these up so you can focus on the hard domain-specific problems, not the infrastructure.


III. Bash Is All You Need

THARIQ: This is my schtick, and I'm going to keep talking about it until everyone agrees with me. Bash is what makes Claude Code so good. Think about what the bash tool actually lets you do: store results of tool calls to files, store memory dynamically, generate scripts and call them, compose functionality using tools like tail, grep, ffmpeg, LibreOffice. It lets the agent use existing software — all the software that already exists on a computer.

If you were designing an agent harness without bash, you'd probably build a search tool, a lint tool, an execute tool. Every time you thought of a new use case, you'd say, "I need another tool." Instead, Claude Code just uses grep. No special package manager. It can run npm run test, it can lint, it can figure out how you lint and run npm run lint — and if you don't have a linter, it can ask, "What if I install ESLint for you?" That's the composability of bash.

Bash for Non-Coding Agents

Let me give a concrete non-coding example. Say you have an email agent and the user asks: "How much did I spend on ride-sharing this week?" Without bash, the agent searches your inbox for "Uber" or "Lyft," gets a hundred emails, and now has to reason about all of them at once. Imagine if someone handed you a stack of papers and said, "Can you just read through all my emails and add up the prices?" That's really hard — you need very high precision and recall.

With bash, you can pipe that search through grep for prices, save them to a file with line numbers, add them up, and then verify each result afterward — checking what each price actually corresponds to. There's a lot more dynamic information processing and work-checking you can do. That's the composability of bash in a non-coding context.

More examples: if you have an inbox API and a contacts API, you can compose them with bash. If you have a video meeting agent and you want to find all the moments in an earnings call where the speaker says "quarterly results," you can use ffmpeg to slice the video and jq to analyze the data afterward. The key insight is that bash is essentially the first code mode — you can take a very wide variety of actions very generically.

AUDIENCE: Do you have stats on how many people use "yolo mode"?

THARIQ: Internally we don't use it much — we just have a higher security posture. I could probably pull that data. Any other questions on bash?


IV. Workflows vs. Agents

THARIQ: You can build both workflows and agents on the agent SDK. Agents are like Claude Code — you want to talk to it in natural language and have it take actions flexibly. Maybe you have an agent that talks to your business data and you want to get insights, build dashboards, answer questions, or write code. That's an agent.

A workflow is more constrained. We do a lot of GitHub Actions internally, for example — you define the inputs and outputs very closely. "Take a PR, give me a code review." With the SDK, you can use structured outputs for that. But when I say "workflow," don't assume it's simpler. We have a bot that triages issues when they come in — a pretty workflow-like thing. But in order to triage issues properly, it needs to clone the codebase, sometimes spin up a Docker container, test things. There are a lot of free-flowing steps in the middle, and then structured output at the end. So the line is blurrier than it looks.


V. Designing the Agent Loop

THARIQ: Here's the meta-learning for designing an agent loop: read the transcripts over and over again. Every time you see the agent running, read it and figure out — what is it doing? Why is it doing this? Can I help it out somehow? We'll do some of that during the demo.

The agent loop has three parts. First: gather context. For Claude Code, that's grepping and finding the files it needs. For an email agent, it's finding the relevant emails. This step gets underestimated. A lot of people skip it or underthink it, but how the agent finds context is critically important.

Second: take action. Does it have the right tools to do its work? Code generation and bash are more flexible ways of taking action than predefined tool calls.

Third: verify the work. This is another really important step that people overlook. If you're thinking of building an agent, ask yourself: can you verify its work? If you can, it's a great candidate for an agent. Code is highly verifiable — you can lint it, at minimum make sure it compiles, and then execute it and see what it does. Deep research is harder to verify; you can require source citations, but that's less rigorous than a compile step. The agents closest to being truly general are the ones with the strongest verification steps.

AUDIENCE: When do you generate a plan?

THARIQ: You'd insert it between the gather context and take action steps. Plans help the agent think through things step by step, but they add latency — so there's a trade-off. In Claude Code, you don't always generate a plan; it depends on the task. The agent SDK has some planning support as well.

AUDIENCE: Can you make the agent create a to-do list and guarantee it will follow it?

THARIQ: Yes — the agent SDK ships with to-do tools. It will maintain and check off to-dos as it goes, and you can display that progress in real time.


VI. Tools vs. Bash vs. Code Generation

THARIQ: You have three things to reach for: predefined tools, bash, and code generation. Most people are only thinking about tools. Let me compare all three.

Tools are extremely structured and very reliable. If you want the fastest output with minimal errors and minimal retries, tools are great. The cons: they're high context usage. If you've ever built an agent with 50 or 100 tools, they take up a lot of context and the model can get confused. There's no discoverability — the model can't explore what the tools can do. And they're not composable.

Bash is very composable. Static scripts, low context usage. It does take some discovery time — if you have the Playwright CLI, for instance, the agent needs to run playwright --help to figure out what it can do, every time. That's kind of powerful because it trades away some context usage for a little latency. Call rates might be slightly lower, but this improves as models get better.

Code generation is highly composable and enables truly dynamic scripts. They take the longest to execute — they may need linting, possibly compilation. API design becomes a very interesting step in this context.

The practical synthesis: keep predefined tools for atomic actions you need a lot of control over. In Claude Code, we don't use bash to write a file — we have a write-file tool, because we want the user to see the output and approve it. We're not composing write-file with other things. Sending an email is another example: any irreversible or externally visible action is a good candidate for a tool. Use bash for composable actions like searching folders, linting code, or managing memory — you can write to files and that becomes your memory system. Use code generation for highly dynamic, flexible logic where you're composing APIs, doing data analysis, or reusing patterns.

AUDIENCE: Will there be ready-made tools for offloading long tool-call results to the file system, to prevent context explosion?

THARIQ: That's a good common practice. I've seen some recent work on this in Claude Code around handling very long outputs. My general approach now is: whenever I have a tool call, I save the results to the file system and have the tool call return the path of the result. That lets the agent recheck its work later by searching across those files.


VII. Skills — Progressive Context Disclosure

THARIQ: Skills are basically a way of allowing an agent to take on longer, more complex tasks by loading in context progressively. For example, we have a bunch of DOCX skills — these tell the agent how to use code generation to produce those files. Skills are, at their core, a collection of files. They're a great example of being very "file system first" because they're really just folders that your agent can cd into and read.

What we've found skills are really good for is repeatable instructions that need a lot of expertise baked in. We released a front-end design skill recently that I really like. It's essentially a very detailed, expert-level prompt on how to do front-end design — written by one of our best AI front-end engineers, with a lot of thought and iteration behind it. That's the value: skills let you capture expert knowledge in a retrievable, composable form.

AUDIENCE: What's the priority order between CLAUDE.md files and skill files?

THARIQ: Honestly, these concepts are so new — Claude Code was released only eight or nine months ago, and skills were released literally two weeks ago. I won't pretend I know all the best practices. The way I think about skills is as progressive context disclosure. The agent is like: "I need to do this. Let me find out how." It reads in the skill, figures out the steps, then executes. You ask it to make a DOCX file, it CDs into the skills directory, reads how to do it, writes some scripts, and keeps going. There's still intuition to build around what exactly belongs in a skill versus CLAUDE.md.

AUDIENCE: Are skills ultimately going to become part of the model itself?

THARIQ: Broadly, yes — the model will get better at a wider variety of tasks, and skills are the best way to handle out-of-distribution tasks right now. My general rule of thumb: I try to rethink and rewrite my agent code every six months, because capabilities have likely changed enough that I've baked in outdated assumptions. The agent SDK is built to advance with capabilities — the bash tool gets better, and since we build on Claude Code, you get those improvements automatically. But things have changed so dramatically in the last year that a general best practice is: we can write code ten times faster now, so we should be willing to throw it out ten times faster as well. If you're a startup, that's arguably your biggest advantage over larger competitors who are stuck in six-month incubation cycles.

AUDIENCE: Why use a skill versus an API?

THARIQ: Both are forms of progressive disclosure to the agent. The choice is use-case dependent. Read the transcript of your agent running and see what it naturally reaches for. If it always wants to think about the API as an api.ts file, do that. Skills are a great introduction to thinking about the file system as a way of storing context, but there are many ways to use the system. One thing to note: skills require the bash tool and a virtual file system, so the agent SDK is basically the only way to use them to their full extent right now.

AUDIENCE: Can we expect a marketplace for skills?

THARIQ: Claude Code has a plugin marketplace you can use with the agent SDK, and we're evolving it over time. It's more of a discovery system than a commercial marketplace, but it does exist right now — you can do /plugins in Claude Code to find some.


VIII. Security & Permissions — The Swiss Cheese Defense

AUDIENCE: If you're using bash as an all-powerful generic tool, is the onus on the agent builder to guard against common attack vectors, or is the model doing that itself?

THARIQ: We call it the Swiss cheese defense. On every layer there are some defenses, and together they block everything — we hope.

At the model layer, we do a lot of alignment work. We just put out a really good paper on reward hacking — strongly recommend checking it out. We try to make the Claude models very aligned. Then at the harness level, we have a lot of permissioning and prompting built in. We actually run a parser on the bash tool so we know fairly reliably what the bash tool is actually doing — and that is definitely not something you want to build yourself. Finally, there's sandboxing. If someone has maliciously taken over your agent, what can it actually do? We've included a sandbox where you can restrict network requests and file system operations outside the designated directory.

The "lethal trifecta," as it's sometimes called, is: execute code in the environment, change the file system, and exfiltrate the code out. If you sandbox the network, that last step becomes very hard. If you're hosting on a sandboxed container — Cloudflare, Modal, E2B, Daytona, any of these sandbox providers — they've also done some level of security. You're not hosting it on your personal computer with your production secrets sitting around.

"ReadOnly" vs. "ReadWrite" File Access

AUDIENCE: How do you ensure role-based access controls?

THARIQ: Generally that's in how you provision your API key or your backend service. I typically create temporary API keys scoped in certain ways. Some people create proxies in between to handle API key injection. On the backend you can check what the agent is trying to do and give it appropriate feedback. The model listens to feedback — if you throw an error, it will read the error output and iterate. That's a powerful property to design around.


IX. Live Demo — The Pokémon Agent

THARIQ: Let's make a Pokémon agent. Pokémon is a game with a lot of information — thousands of Pokémon, each with a ton of moves. There is a public PokéAPI. I chose it because I know you all have your own complex APIs, and I wanted to choose something with a fairly complex API that I haven't tried building against before.

One thing a user might want to do is build a competitive Pokémon team. I love Pokémon but know very little about competitive play. Could an agent help me with that? That would be cool. My goal is to build an agent that can chat about Pokémon, and we'll see how far we get.

The first step was: I gave Claude Code the prompt "go search the PokéAPI for its API and create a TypeScript library." Here's what it generated — a PokemonAPI interface with methods like getByName, listPokemon, getAllPokemon, getSpecies, getAbilities, and the same for moves. It also created a CLAUDE.md describing this TypeScript SDK and instructing the agent to write scripts in an examples directory and execute those scripts to handle queries. That's my agent, really — a prompt to generate a TypeScript library plus a CLAUDE.md.

Comparing Tools-Only vs. Bash + Code Generation

I also built a version using the messages/completions API directly with predefined tools: getPokemon, getPokemonSpecies, getPokemonAbility, getPokemonType, getMove. You can see how with the tools-only approach, I had to define all of these upfront. And there's only so many parameters I could anticipate.

When I ask the Claude Code version "what are the Generation 2 water Pokémon?", it writes a script, fetches the PokéAPI directly, iterates over 200+ Pokémon, checks their types, and returns the list. It's using code generation to handle a query I didn't explicitly anticipate when I built the harness. That's the key difference — the bash-and-codegen version can handle queries I never pre-designed tools for.

Competitive Analysis with Smogon Data

For competitive play, there's a text file from Smogon — an online library that stores all Pokémon, their moves, who they work well with, who counters them. I put this in the data folder and asked: "I want to make a team around Venusaur. Can you give me some suggestions based on the Smogon data?"

What it did was start grepping through that text file — finding Venusaur's profile, then finding other Pokémon that mentioned Venusaur as a teammate or counter. It ran searches, found interesting synergies, wrote a script to analyze the most common teammates, and returned a full team suggestion. All based on a raw text file. That's the power of the approach — I didn't build a structured Smogon API. I gave it a text file and bash access and it figured out the rest.

AUDIENCE: Is that code going to be on GitHub somewhere?

THARIQ: Yeah, it's on my personal GitHub. I'll push the latest changes and also tweet about it — I'm @TRQ212 on Twitter and post a lot about agent SDK stuff.


X. The Spreadsheet Agent Exercise

THARIQ: Let's think through a spreadsheet agent. You want it to be able to search, take action, and verify its work. How would you approach it? Take a minute to think about it.

What's the best way for an agent to search a spreadsheet? You've got a CSV. The agent wants to search it. What does it do?

AUDIENCE: Convert it to CSV and grep. Look at all the headers.

THARIQ: Good. Headers give you a starting point, but a spreadsheet is a multi-dimensional problem. If you ask "what's the revenue in 2026?" you need to find a revenue column and then filter by 2026. Pulling headers alone gives you column names but not row values. Other ideas?

AUDIENCE: AWK. SQLite on the CSV directly. Use the Google Sheets API.

THARIQ: All great. I love the SQLite one — querying a CSV via SQLite is a creative way to think about API design. If you can translate your data source into a SQL interface, the agent knows SQL extremely well. That transformation step is one of the most powerful design moves you can make for an agentic search interface.

Something else worth noting: XLSX files are XML under the hood. You can do XML path queries against the raw file, and there are libraries that support that. So you've got at least four approaches: grep on headers, AWK, SQLite wrapper, XML query. The key insight is that gathering context is really creative work. If you've only tried one iteration, that's probably not enough. Try SQL, try grep, try AWK — run tests across approaches, see what the agent naturally does well, and iterate.

Taking Action and Verifying Work

Taking action in a spreadsheet looks a lot like gathering context — inserting a 2D array, running a SQL update, editing XML. The APIs tend to be similar going both directions. Then verification: check for null pointers. Look for anomalies — did a value change that shouldn't have? One pattern is to use a sub-agent for adversarial verification. Give a fresh agent the output with no context about who made it and ask it to critique the work. As models get better at reasoning, that adversarial sub-agent gets better too.

AUDIENCE: What about undoing mistakes? If the agent deletes a whole spreadsheet, what then?

THARIQ: This is a really important consideration when choosing what domains agents are good at. How reversible is the work? Code is very reversible — you can undo via git history. Claude Code does atomic operations and I use git constantly through it; I don't type git commands anymore. Computer use is a bad example of reversibility because every action compounds the state. If you're thinking about building a spreadsheet agent, try to turn it into a reversible state machine: store state at checkpoints so the user can say, "my spreadsheet is messed up, go back to where we were." Someone actually built a "time travel" tool for a coding agent that let it revert to a point before something went wrong. Those tools are still early but the idea is sound.


XI. Sub-Agents and Context Management

AUDIENCE: Do all agents share the same context window?

THARIQ: Sub-agents are one of the most important primitives for managing context, and I haven't talked about them enough. Sub-agents are great for when you need to do a lot of work and return just the answer to a main agent. For a spreadsheet search, the main agent might spin up three sub-agents in parallel — one to summarize sheet one, one for sheet two, one for sheet three — and then reason over all three results. The sub-agents do the expensive exploratory work; the main agent just sees the distilled output.

Sub-agents with bash is something Claude Code handles really well — better than I've seen in any other framework, honestly. Running parallel sub-agents with bash becomes very complex (race conditions and file system conflicts are real), and there's a lot of engineering we've done to solve that. In the agent SDK you can just ask it to spin up three sub-agents to do a task and it will do that.

AUDIENCE: What fraction of the context window can you use before hitting diminishing returns?

THARIQ: When I talk to people using Claude Code, they'll mention being on their fifth compact, and I'm genuinely surprised — I've almost never done a compact. I tend to clear the context window very often. In code, the state is in the files of the codebase, not in the chat history. If I've made some changes, Claude Code can just look at the git diff and continue a new task without needing to know my entire conversation history. So for code, I clear context very aggressively.

For your own agents — a spreadsheet agent, say — context management is harder because your users don't know what a context window is. The UX design challenge is: can you reset conversation state gracefully? In a spreadsheet, a lot of the state is in the spreadsheet itself, not in the chat history, so the agent probably doesn't need to carry as much forward. Can you store user preferences as it goes, so you remember some things without needing the full transcript? There's a lot of design space here, but you are trying to minimize context usage without the user noticing.


XII. Hooks — Deterministic Verification

AUDIENCE: I haven't heard you talk about hooks yet. What's your take?

THARIQ: Hooks are great, and we do ship with them. Hooks are a way of doing deterministic verification or inserting context at key moments. We fire these as events and you can register handlers in the agent SDK.

Some examples: you can run a verification check on the spreadsheet after every tool call. Or imagine you're working with an agent on a spreadsheet and the user is also editing the spreadsheet in parallel. A hook can detect that the user has changed something and inject those changes into the agent's context — giving it live updates between tool calls. That's a really interesting way to use hooks.

For determinism: if an agent hallucinates or skips a step — say, it guesses a Pokémon stat instead of actually running a script to check — a hook can intercept the response and inject feedback: "Please make sure you write a script and read the actual data." In Claude Code, we have a rule that if the agent tries to write to a file it hasn't read yet, we throw an error and say "you haven't read this file yet, try reading it first." That's deterministic verification at the tool level, and hooks let you build the same kind of thing for your own agents.

More documentation is in the agent SDK docs, and I'm happy to talk through specific use cases afterward.


XIII. Q&A — Scaling, Reproducibility, and Large Codebases

Reproducibility and Helper Scripts

AUDIENCE: Let's say I've done this prototyping and found something that works. How do I convert that into a reproducible, productionizable thing?

THARIQ: I'd start in CLAUDE.md — for example, one of my early runs of the Pokémon agent ignored my pre-built TypeScript API and wrote JavaScript. I should have been more explicit in CLAUDE.md: "you should use this library." The second thing is: summarize what worked in terms of helper scripts and write something like an agent.ts script to run the tests again. Good helper scripts mean the agent can discover and verify what tools it has available.

When the Agent Ignores the Script and Just Answers from Memory

AUDIENCE: My Pokémon agent tries once or twice to use the scripts, fails, and then just returns a comparison table from its training data. Any advice?

THARIQ: This is a good problem and there is some messiness here. Pokémon is in-distribution for the model, so it will sometimes just answer from memory rather than actually checking. One of the best solutions is hooks: you can check whether the response includes a script execution, and if not, inject feedback — "please make sure you write a script, please make sure you read the actual data." It adds a deterministic guardrail without retraining the model. That said, it is an art — sometimes you just need to push harder on it through the prompt or iterate on the verification logic.

Scaling to Massive Codebases (50M+ Lines)

AUDIENCE: I'm working with a 50-million-plus line codebase. Standard grep doesn't work at that scale. I'm building my own semantic indexing. Is Anthropic thinking about making that more native to the product?

THARIQ: Is what you're building going to be obsolete in a couple of months? Generally, with AI — yes. [laughter] But let me give a real answer. Semantic search has trade-offs: it's more brittle, and the model isn't trained on your specific semantic index, so the queries can be unpredictable. What I've seen working well for very large codebases is good CLAUDE.md files — structured context that tells the agent where things live — and starting the agent in the specific subdirectory you want it to work in rather than trying to index the entire 50 million lines at once. Good verification steps, hooks, and linting matter a lot here. We don't use custom semantic indexing for Claude Code itself, but we do use good context files and scoped starting points. It's not a perfect answer, but it's what works today.

Monetization and Pricing Models

AUDIENCE: Agents are pricey. How are you thinking about monetization when the margins all flow back to Anthropic?

THARIQ: Agents are pricey right now — models have just started to become truly agentic and we focus on the most intelligent models we can build. The general software answer applies here: you'd rather charge fewer people more money for solving a genuinely hard problem than charge many people a little for something they could do themselves. Find the use cases where people have a hard problem and will pay meaningfully for a solution. On pricing structure — subscription or usage-based — it really depends on your user base. Claude Code does a mix: rate limits with overage usage-based pricing above the limit. Design your monetization model up front, because it's hard to walk back pricing promises once users expect them.


[Applause. End of session.]


Transcript lightly edited for clarity. Filler words and false starts have been removed; all technical content is preserved verbatim or in close paraphrase. Speaker's GitHub: github.com/thariq. Twitter: @TRQ212.

3.22.2026

Workshop Claude Agent SDK của Thariq Shihipar — Giải Thích Cho Người Không Phải là Lập Trình Viên

Tác giả: Claude AI, dưới sự dẫn dắt và những chỉnh sửa cùa Học Trò.

Dựa trên workshop lập trình viên một ngày do Anthropic tổ chức. Diễn giả: Thariq Shihipar, Anthropic. Bản ghi âm gốc đã được tái cấu trúc và mọi khái niệm kỹ thuật đều được giải thích bằng ngôn ngữ đơn giản.


Mở Đầu — Tác Nhân Là Gì?

Để hiểu những gì Thariq đang dạy, trước tiên bạn cần hiểu ba thế hệ công cụ AI mà ông trình bày, vì hầu hết mọi điều ông nói đều được xây dựng trên nền tảng đó.

Thế hệ đầu tiên là lệnh gọi AI đơn. Bạn có một mô hình AI — hãy nghĩ về mô hình như "bộ não" AI, một chương trình được huấn luyện trên lượng văn bản khổng lồ có thể hiểu và tạo ra ngôn ngữ — và bạn gửi cho nó một câu hỏi rồi nhận lại một câu trả lời. "Phân loại email này là spam hay không phải spam." Chỉ vậy thôi. Một lệnh nhắc vào, một câu trả lời ra. Nó hữu ích nhưng hạn chế. AI không có bộ nhớ về những gì nó vừa làm, không có khả năng tra cứu bất cứ điều gì và không có cách nào để thực hiện hành động trong thế giới thực.

Thế hệ thứ hai là luồng làm việc (workflow). Luồng làm việc là một chuỗi các lệnh gọi AI có cấu trúc, được lập kế hoạch trước, được ghép lại với nhau bởi một lập trình viên. Hãy nghĩ nó như một công thức nấu ăn: "Bước một, lấy email của người dùng. Bước hai, yêu cầu AI gán nhãn cho nó. Bước ba, lưu nhãn vào cơ sở dữ liệu." Mỗi bước được lập trình viên xác định trước. AI không có lựa chọn về việc làm tiếp theo — nó chỉ đơn giản hoàn thành phần của mình trong dây chuyền lắp ráp. Luồng làm việc mạnh mẽ hơn, nhưng chúng cứng nhắc. Nếu xuất hiện một tình huống mới mà lập trình viên chưa dự kiến, luồng làm việc sẽ gãy.

Thế hệ thứ ba — và là thế hệ mà toàn bộ workshop này đề cập — là tác nhân (agent). Tác nhân là một AI tự mình quyết định những bước cần thực hiện, theo thứ tự nào, trong bao lâu. Thariq nói rõ: "Các tác nhân tự xây dựng ngữ cảnh của riêng họ, tự quyết định hành trình của mình và hoạt động rất tự chủ." Ngữ cảnh ở đây là từ bạn sẽ thấy liên tục trong lĩnh vực này. Mô hình AI chỉ có thể thấy một lượng văn bản hạn chế tại một thời điểm — về cơ bản đó là bộ nhớ làm việc của nó. Điều này được gọi là cửa sổ ngữ cảnh (context window). Một lệnh gọi AI đơn chỉ thấy câu hỏi của bạn. Một tác nhân chủ động đi ra ngoài thu thập thông tin nó cần, tải vào cửa sổ ngữ cảnh đó, xử lý vấn đề, thực hiện hành động và kiểm tra kết quả của chính mình. Nó không theo công thức; nó đang tự tìm ra công thức khi tiến hành.

Ví dụ mà Thariq sử dụng là Claude Code — trợ lý lập trình của chính Anthropic. Claude Code là tác nhân đầu tiên ông thấy chạy liên tục mười, hai mươi, ba mươi phút mà không cần con người điều khiển. Bạn nói với nó bằng tiếng Anh thông thường điều bạn muốn — "thêm tính năng đăng nhập người dùng vào ứng dụng của tôi" — và nó đọc codebase của bạn, tìm ra những gì cần thay đổi, viết code, chạy các bài kiểm thử và sửa lỗi, tất cả một mình. Đó là điều làm cho nó trở thành tác nhân thay vì luồng làm việc: nó đưa ra quyết định ở mọi bước, không thực thi một kịch bản được định nghĩa trước.

Claude Agent SDK — chủ đề của toàn bộ workshop này — là một bộ công cụ mà Anthropic xây dựng đặc biệt để giúp các lập trình viên khác dễ dàng xây dựng tác nhân của riêng họ hơn. Không phải tác nhân lập trình như Claude Code, mà là bất kỳ loại tác nhân nào: tác nhân dịch vụ khách hàng, tác nhân tài chính, tác nhân nghiên cứu pháp lý, tác nhân chăm sóc sức khỏe. SDK đóng gói tất cả những bài học kinh nghiệm quý báu từ việc xây dựng Claude Code để bạn không phải tự giải quyết những vấn đề đó.


I. Claude Agent SDK — Tại Sao Chúng Tôi Xây Dựng Nó

SDK là viết tắt của Bộ Công Cụ Phát Triển Phần Mềm (Software Development Kit). Hãy nghĩ nó như một hộp công cụ mà ai đó đã chuẩn bị sẵn cho bạn. Thay vì phải đến cửa hàng phần cứng, mua từng dụng cụ riêng lẻ, tìm hiểu thương hiệu nào tốt nhất và học cách sử dụng từng cái từ đầu, bạn nhận được một hộp công cụ đã đóng gói sẵn với mọi thứ được tổ chức và sẵn sàng sử dụng. Claude Agent SDK là hộp công cụ đóng gói sẵn của Anthropic để xây dựng các tác nhân AI.

Thariq giải thích lý do nó tồn tại theo một cách thẳng thắn đáng ngạc nhiên: các kỹ sư của Anthropic liên tục phải xây dựng lại những phần giống nhau. Mỗi lần họ muốn xây dựng một tác nhân mới cho một dự án nội bộ — theo dõi lỗi, xem xét code, giúp đỡ nhóm tài chính — họ lại thấy mình đang giải quyết những vấn đề cơ sở hạ tầng tương tự. Làm thế nào để xử lý khi AI gặp lỗi khi gọi công cụ? Làm thế nào để ngăn cuộc hội thoại cạn kiệt bộ nhớ? Phải làm gì khi tác nhân chạy một giờ và cửa sổ ngữ cảnh đầy? Mỗi nhóm đang giải quyết những vấn đề này một cách độc lập, viết code trùng lặp và mắc phải những sai lầm tương tự.

Một khi Claude Code được phát hành cho công chúng, điều bất ngờ đã xảy ra. Các kỹ sư bắt đầu sử dụng nó cho công việc của họ, điều đó có lý — nó là công cụ lập trình. Nhưng sau đó nhóm tài chính bắt đầu sử dụng nó. Nhóm marketing. Các nhà khoa học dữ liệu. Mọi người đang sử dụng một tác nhân lập trình để thực hiện các nhiệm vụ không liên quan gì đến code, và nó hoạt động vì cách tiếp cận cơ bản đủ tổng quát. Quan sát đó đã làm rõ cơ hội: nếu kiến trúc của Claude Code có thể được trích xuất và đóng gói, bất kỳ ai cũng có thể xây dựng một tác nhân có năng lực trên đó mà không cần giải quyết lại các vấn đề nền tảng.

SDK tích hợp những bài học khó khăn nhất của Anthropic. Lỗi sử dụng công cụ — tức là các tình huống mà AI cố gọi một trong các hàm có sẵn của nó và có điều gì đó không ổn — được xử lý khéo léo. Nén ngữ cảnh được tích hợp sẵn; đây là quá trình tóm tắt các phần cũ hơn của cuộc hội thoại khi cửa sổ ngữ cảnh bắt đầu đầy, để tác nhân có thể tiếp tục làm việc trong các nhiệm vụ dài mà không mất phương hướng. Các thực tiễn tốt nhất cho các nhiệm vụ chạy dài — tác nhân có thể chạy một giờ hoặc hơn — được mã hóa vào các giá trị mặc định của SDK. Khi bạn xây dựng trên SDK, bạn thừa hưởng tất cả điều này miễn phí.

Thariq nói thẳng về một điều: SDK có quan điểm riêng (opinionated). Có quan điểm riêng có nghĩa là nó đưa ra lựa chọn cho bạn và hướng bạn đến một cách thực hiện cụ thể. Điều này trái ngược với bộ công cụ trung lập, làm theo ý bạn. SDK có quan điểm mạnh mẽ về cách xây dựng tác nhân, vì Anthropic tin rằng quan điểm đó dẫn đến kết quả tốt hơn. Quan điểm lớn nhất mà nó giữ — và Thariq quay lại nhiều lần — là dòng lệnh, cụ thể là bash shell, là công cụ mạnh mẽ nhất bạn có thể trao cho một tác nhân.


II. Khung Hỗ Trợ — Nhiều Hơn Chỉ Là Một Mô Hình

Một trong những ý tưởng quan trọng nhất trong workshop này là một tác nhân AI có năng lực không chỉ là một mô hình AI ngồi một mình. Mô hình là bộ não, nhưng một bộ não không có thân xác, không có không gian làm việc và không có bộ công cụ thì không thể thực hiện được nhiều. Toàn bộ cơ sở hạ tầng xung quanh — mọi thứ hỗ trợ và trao quyền cho mô hình — là thứ mà Thariq gọi là Khung Hỗ Trợ (Harness).

Hãy tưởng tượng một nhân viên mới tại một công ty. Nhân viên đó (mô hình AI) có thể rất tài năng, nhưng vào ngày đầu tiên họ không thể làm được nhiều nếu không có bàn làm việc, máy tính, quyền truy cập vào các tệp của công ty, danh sách trách nhiệm và đồng nghiệp để hỏi khi cần. Khung hỗ trợ là tất cả những thứ đó — bàn làm việc, máy tính, quyền truy cập, hướng dẫn. Không có khung hỗ trợ, mô hình ngồi trong phòng với một câu hỏi mà không có cách nào để điều tra, hành động hay xác minh bất cứ điều gì.

Khung hỗ trợ có nhiều thành phần, và Thariq liệt kê chúng một cách rõ ràng. Đầu tiên là các công cụ — đây là những hành động cụ thể mà AI được phép thực hiện, như đọc tệp, tìm kiếm web hoặc gửi tin nhắn. Hãy nghĩ các công cụ như các nút trên bảng điều khiển: AI biết các nút tồn tại, biết mỗi nút làm gì và có thể nhấn chúng khi cần. Sau đó là hệ thống tệp (file system), đơn giản là bộ nhớ lưu trữ của máy tính — các thư mục và tệp mà tác nhân có thể đọc, ghi vào và sắp xếp. Thariq đặt ra rằng hệ thống tệp không chỉ là bộ nhớ lưu trữ; nó là một dạng kỹ thuật ngữ cảnh. Thay vì cố giữ mọi thứ trong bộ nhớ làm việc của AI cùng một lúc, bạn có thể chuyển thông tin sang tệp và để tác nhân đọc lại những gì nó cần khi cần.

Ngoài ra còn có các lệnh nhắc cốt lõi của tác nhân — những hướng dẫn thường trực cho tác nhân biết nó là ai và nên hành xử như thế nào. Một tệp đặc biệt gọi là CLAUDE.md phục vụ chức năng này trong hệ thống của Anthropic. Mỗi khi tác nhân khởi động hoặc khởi động lại, nó đọc CLAUDE.md trước tiên. Bạn có thể nghĩ nó như sổ tay nhân viên: nó cho tác nhân biết các quy tắc của công việc cụ thể này, những công cụ nào có sẵn, những gì nó nên và không nên làm.

Ngoài những yếu tố cơ bản đó, khung hỗ trợ bao gồm các kỹ năng (skills) — các gói hướng dẫn có thể tái sử dụng mà tác nhân có thể tải theo yêu cầu khi gặp phải nhiệm vụ chuyên biệt. Nó bao gồm các tác nhân phụ (sub-agents) — các tác nhân nhỏ mà tác nhân chính có thể tạo ra để làm việc song song trên các vấn đề con. Nó bao gồm tìm kiếm web, nén ngữ cảnh (quá trình tóm tắt cuộc hội thoại cũ để giải phóng bộ nhớ), móc nối (hooks — các điểm kiểm tra tự động chạy các kiểm tra xác minh) và bộ nhớ (lưu trữ thông tin liên tục qua các phiên). Mỗi thứ trong số này sẽ được giải thích trong chương của riêng nó. Điểm quan trọng bây giờ chỉ đơn giản là: một tác nhân mạnh mẽ là một hệ thống, không chỉ là một mô hình. Claude Agent SDK đóng gói toàn bộ hệ thống đó để bạn có thể triển khai mà không cần tự xây dựng từng phần.


III. Bash Là Tất Cả Những Gì Bạn Cần

Nếu có một ý tưởng nào trong workshop này mà Thariq đam mê nhất, đó chính là ý tưởng này. Bash là shell dòng lệnh — giao diện dựa trên văn bản nơi bạn gõ lệnh trực tiếp vào hệ điều hành. Đó là cửa sổ đen trên màn hình của lập trình viên nơi bạn có thể thấy các dòng như ls, grep hoặc cd. Nếu bạn chưa bao giờ sử dụng nó, bạn có thể nghĩ nó như "bảng điều khiển của lập trình viên" dành cho máy tính. Nó có trước các giao diện đồ họa, nó cực kỳ mạnh mẽ và hầu như mọi máy tính trên thế giới đều có nó.

Lập luận của Thariq là việc cho tác nhân AI quyền truy cập vào bash về cơ bản mạnh mẽ hơn so với việc cho nó một danh sách các công cụ tùy chỉnh. Đây là lý do. Khi bạn cho tác nhân một danh sách công cụ — chẳng hạn, công cụ searchEmail, công cụ calculateSum, công cụ downloadFile — bạn, với tư cách lập trình viên, đang quyết định trước những gì tác nhân được phép làm. Mỗi khả năng mới đòi hỏi bạn phải đi viết thêm một công cụ. Bạn luôn đi sau một bước so với nhu cầu của tác nhân. Nhưng khi bạn cho tác nhân quyền truy cập bash, bạn cấp cho nó quyền truy cập vào mọi phần mềm đã được cài đặt trên máy tính. Tác nhân có thể dùng grep để tìm kiếm một mẫu trong hàng nghìn tệp. Nó có thể dùng ffmpeg — một chương trình để xử lý video và âm thanh — để trích xuất các đoạn clip. Nó có thể dùng jq để phân tích dữ liệu có cấu trúc. Nó có thể cài đặt phần mềm mới nếu cần. Nó có thể kết hợp nhiều chương trình với nhau bằng toán tử pipe, chuyển đầu ra của một lệnh trực tiếp vào đầu vào của lệnh khác. Tính khả kết hợp đó chính là chìa khóa.

Thariq đưa ra một ví dụ cụ thể để làm cho điều này trở nên rõ ràng. Giả sử bạn có một tác nhân email và người dùng hỏi: "Tháng này tôi đã chi bao nhiêu tiền cho dịch vụ đặt xe?" Không có bash, tác nhân lấy mọi email đề cập đến Uber hay Lyft — có thể là hàng trăm email — và sau đó phải suy luận qua tất cả chúng cùng một lúc, cố gắng trích xuất số tiền và cộng chúng lại. Điều đó tốn kém về mặt nhận thức và dễ mắc lỗi, giống như đưa cho một người một chồng một trăm tờ giấy và nói "đọc hết tất cả rồi cho tôi biết tổng số." Với bash, tác nhân có thể dùng grep để trích xuất chỉ những dòng trong các email đó chứa số tiền, lưu chúng vào một tệp tạm, dùng lệnh khác để cộng chúng lại, và sau đó kiểm tra chéo một vài kết quả để xác nhận chúng hợp lý. Nhiệm vụ mơ hồ và ngập tràn trở thành một phép tính chính xác, có thể xác minh được.

Cách tiếp cận này hoạt động tốt như nhau cho các nhiệm vụ không liên quan đến kỹ thuật. Một tác nhân xử lý video có thể dùng ffmpeg để cắt một đoạn ghi âm cuộc họp mỗi khi từ "doanh thu" được phát hiện. Một tác nhân dữ liệu có thể đưa kết quả API qua jq để trích xuất chỉ những trường nó cần. Một tác nhân email có thể kết hợp API hộp thư đến với API danh bạ bằng bash scripting. Nguyên tắc cơ bản là bash coi mọi phần mềm hiện có như một khối xây dựng tiềm năng. Thay vì xây dựng lại bánh xe mỗi khi bạn cần một khả năng mới, tác nhân dùng bất kỳ công cụ nào đã tồn tại trên máy tính và kết hợp nó với mọi thứ khác.

Thariq cũng nêu ra một điểm thực tế về bộ nhớ. Khi tác nhân tính toán điều gì đó — chẳng hạn, danh sách chi phí đặt xe — nó có thể ghi kết quả đó vào một tệp trên đĩa. Sau này, nếu nó muốn kiểm tra lại công việc của mình hoặc thêm dữ liệu, nó không cần phải làm lại phép tính. Nó chỉ cần đọc tệp trở lại. Hệ thống tệp, kết hợp với bash, trở thành bộ nhớ linh hoạt, bền vững tồn tại bên ngoài cửa sổ ngữ cảnh. Đây là triết lý thiết kế trung tâm của Claude Agent SDK: hệ thống tệp không chỉ là bộ nhớ lưu trữ, nó là sự mở rộng của tư duy của tác nhân.


IV. Luồng Làm Việc và Tác Nhân

Thariq vạch ra ranh giới giữa hai loại thứ bạn có thể xây dựng với SDK: luồng làm việc và tác nhân. Hiểu sự phân biệt này sẽ giúp bạn không áp dụng sai công nghệ và không bị nhầm lẫn khi thấy từ "agent" được dùng để có nghĩa rất khác nhau.

Một tác nhân, như được mô tả trong phần mở đầu, là tự chủ. Nó tự quyết định các bước của mình. Bạn cho nó một mục tiêu bằng ngôn ngữ tự nhiên — "giúp tôi phân tích dữ liệu kinh doanh của mình và tạo bảng điều khiển" — và nó tự tìm ra cách đạt được điều đó. Nó có thể grep qua các tệp của bạn, viết một số code, chạy code, xem đầu ra, nhận thấy điều gì đó bất ngờ, hỏi bạn một câu hỏi làm rõ, rồi tiếp tục. Con đường không được biết trước. Tác nhân xây dựng nó khi tiến hành, phản hồi với những gì nó khám phá trên đường đi.

Luồng làm việc giống như máy bán hàng tự động hơn. Bạn xác định rõ đầu vào, bạn xác định rõ đầu ra, và các bước ở giữa phần lớn là cố định. Thariq đưa ra ví dụ về luồng làm việc GitHub Actions — một công cụ tự động hóa phổ biến được các nhóm phần mềm sử dụng. Bạn xác định: "Khi một pull request đến, chạy các bước này theo thứ tự này và tạo ra đầu ra này." Nó có cấu trúc, bị ràng buộc và có thể dự đoán được. Đầu ra có cấu trúc — tức là các phản hồi được định dạng theo cách cụ thể, có thể đọc được bằng máy — phù hợp tự nhiên ở đây. Nếu bạn muốn AI xem xét một đoạn code và luôn trả về đối tượng JSON với các trường như rating, summarysuggested_changes, đó là tư duy luồng làm việc.

Nhưng đây là sắc thái mà Thariq muốn bạn nắm giữ: ranh giới giữa luồng làm việc và tác nhân trong thực tế rất mờ nhạt. Ông đưa ra ví dụ về bot phân loại lỗi. Nhìn bề ngoài nghe có vẻ như một luồng làm việc đơn giản: một issue mới đến trên GitHub, bot đọc nó, gán nhãn và phân công cho đội ngũ đúng. Đầu vào, xử lý, đầu ra — sạch sẽ và có cấu trúc. Nhưng thực sự làm tốt công việc đòi hỏi bot phải sao chép kho mã nguồn, khởi tạo container Docker (một môi trường ảo độc lập nơi code có thể chạy an toàn), chạy code để tái tạo lỗi, kiểm tra xem các lỗi tương tự đã xuất hiện trước đây chưa, và sau đó đưa ra phán đoán về mức độ nghiêm trọng. Có rất nhiều bước linh hoạt, mở ở giữa, ngay cả khi đầu ra cuối cùng là một nhãn có cấu trúc. Sự phân biệt luồng làm việc-tác nhân ít liên quan đến định dạng đầu ra hơn và liên quan nhiều hơn đến mức độ tự do mà AI có trong việc quyết định cách đến đó.

Hướng dẫn thực tế của Thariq là mặc định chuyển sang tác nhân khi vấn đề lộn xộn và không được xác định rõ ràng, và sử dụng luồng làm việc — với đầu ra có cấu trúc — khi vấn đề được xác định rõ và các bước đã biết. Hầu hết các vấn đề kinh doanh trong thế giới thực, ông gợi ý, phức tạp hơn bề ngoài, và một luồng làm việc hoàn toàn cứng nhắc cuối cùng sẽ gãy khi thực tế không khớp với kế hoạch. SDK hỗ trợ cả hai mẫu, và cơ sở hạ tầng cơ bản giống nhau phục vụ cả hai cách tiếp cận.


V. Thiết Kế Vòng Lặp Tác Nhân

Mọi tác nhân, bất kể làm gì, đều hoạt động trong một vòng lặp. Nó không nhận một câu hỏi và trả về một câu trả lời. Nó đi qua một quy trình — thu thập thông tin, thực hiện hành động, kiểm tra kết quả — lặp đi lặp lại cho đến khi hoàn thành công việc hoặc bị kẹt. Thariq gọi đây là vòng lặp tác nhân, và hiểu ba giai đoạn của nó là khuôn khổ thực tế nhất ông cung cấp cho bất kỳ ai muốn xây dựng tác nhân của riêng họ.

Giai đoạn đầu tiên là thu thập ngữ cảnh. Ngữ cảnh, theo thuật ngữ AI, có nghĩa là tất cả thông tin mà mô hình hiện có để suy luận. Trước khi tác nhân có thể làm bất cứ điều gì hữu ích, nó cần phải hiểu tình huống. Đối với tác nhân lập trình như Claude Code, thu thập ngữ cảnh có nghĩa là tìm và đọc các tệp mã nguồn có liên quan. Đối với tác nhân email, nó có nghĩa là tìm kiếm hộp thư đến cho các tin nhắn có liên quan. Đối với tác nhân hỗ trợ khách hàng, nó có nghĩa là lấy lịch sử tài khoản của khách hàng. Thariq nói rằng bước này bị đánh giá thấp hơn bất kỳ bước nào khác — hầu hết các lập trình viên vội qua nó để đến phần thú vị (thực hiện hành động), nhưng mức độ tác nhân thu thập ngữ cảnh của nó gần như hoàn toàn quyết định chất lượng của những gì nó làm tiếp theo. Bác sĩ nắm rõ tiền sử bệnh nhân đưa ra chẩn đoán tốt hơn so với người đoán mò. Tác nhân thu thập ngữ cảnh có liên quan kỹ lưỡng cho kết quả tốt hơn so với tác nhân vội thực hiện hành động với thông tin không đầy đủ.

Giai đoạn thứ hai là thực hiện hành động. Đây là nơi tác nhân thực sự làm gì đó: viết code, gửi tin nhắn, sửa đổi tệp, gọi API, tạo báo cáo. Chất lượng của giai đoạn này phụ thuộc nhiều vào các công cụ và khả năng mà tác nhân được trao — đó là lý do tại sao sự lựa chọn giữa các công cụ được định nghĩa trước, bash và tạo code (được thảo luận trong chương tiếp theo) quan trọng đến vậy.

Giai đoạn thứ ba là xác minh. Sau khi thực hiện hành động, tác nhân nên kiểm tra xem nó có thực sự hoạt động không. Đây là giai đoạn Thariq nói hầu hết người mới bắt đầu bỏ qua hoàn toàn, và đó là điều phân biệt tác nhân đồ chơi với tác nhân đáng tin cậy. Đối với tác nhân lập trình, xác minh có thể có nghĩa là chạy code để xem nó có biên dịch không, sau đó chạy các bài kiểm thử tự động để xem nó có vượt qua không. Biên dịch là nhị phân — code hoặc biên dịch được hoặc không — điều này làm cho nó trở thành bước xác minh cực kỳ đáng tin cậy. Đối với tác nhân nghiên cứu, xác minh có thể có nghĩa là kiểm tra rằng mọi tuyên bố trong báo cáo được tạo ra đều được hỗ trợ bởi trích dẫn nguồn. Đối với tác nhân bảng tính, nó có thể có nghĩa là kiểm tra rằng các tổng cộng lại chính xác trước khi trả kết quả cho người dùng.

Thariq đưa ra quan sát quan trọng về những nhiệm vụ nào là ứng viên tốt cho các tác nhân: những nhiệm vụ có xác minh dễ dàng và đáng tin cậy. Code rất tốt vì bạn có thể lint nó (một linter là chương trình tự động kiểm tra code về các lỗi phổ biến và vi phạm phong cách), biên dịch nó và chạy nó. Các bước xác minh là khách quan và rẻ. Nghiên cứu chuyên sâu khó khăn hơn — bạn có thể yêu cầu trích dẫn, nhưng trích dẫn không chứng minh văn bản đại diện chính xác cho nguồn. Bạn càng gần được với xác minh tự động, khách quan thì tác nhân của bạn sẽ hoạt động đáng tin cậy hơn theo thời gian.

Một thành viên khán giả hỏi về lập kế hoạch — khi nào tác nhân nên viết ra kế hoạch trước khi hành động? Thariq đặt lập kế hoạch giữa việc thu thập ngữ cảnh và thực hiện hành động: tác nhân thu thập thông tin, xây dựng kế hoạch, sau đó thực thi. Các kế hoạch giúp AI suy nghĩ từng bước, cải thiện độ chính xác trên các nhiệm vụ phức tạp. Nhưng chúng thêm độ trễ, có nghĩa là thêm thời gian trước khi có bất cứ điều gì có thể nhìn thấy xảy ra. SDK hỗ trợ lập kế hoạch, và quyết định có bao gồm bước lập kế hoạch hay không phụ thuộc vào nhiệm vụ có đủ phức tạp để được hưởng lợi hay không. Thariq cũng lưu ý rằng SDK đi kèm với các công cụ danh sách việc cần làm — tác nhân có thể duy trì danh sách kiểm tra các nhiệm vụ con và đánh dấu chúng hoàn thành khi tiến hành, cho người dùng cập nhật tiến độ trực tiếp theo thời gian thực.


VI. Công Cụ, Bash và Tạo Code

Khi bạn xây dựng tác nhân, bạn có ba cách về cơ bản khác nhau để trao cho nó khả năng hành động trong thế giới: các công cụ được định nghĩa trước, lệnh bash và tạo code. Hầu hết các lập trình viên chỉ biết về lựa chọn đầu tiên. Thariq đi qua cả ba, giải thích khi nào mỗi cái là lựa chọn đúng.

Các công cụ được định nghĩa trước là các hàm bạn xác định trước với tư cách lập trình viên. Bạn viết một hàm gọi là searchDatabase, đưa cho nó một mô tả và nói với AI rằng nó có thể gọi hàm đó khi cần tìm kiếm cơ sở dữ liệu. AI gọi nó, nhận kết quả và tiếp tục suy luận. Các công cụ là tùy chọn có cấu trúc và đáng tin cậy nhất trong ba lựa chọn — AI luôn nhận kết quả có thể dự đoán, được xác định rõ. Chúng lý tưởng khi bạn cần phản hồi nhanh, không có lỗi và biết chính xác những hành động nào tác nhân sẽ cần thực hiện. Nhược điểm là các công cụ tốn kém về mặt ngữ cảnh. Mỗi công cụ bạn xác định tiêu thụ một phần bộ nhớ làm việc của AI chỉ bằng cách tồn tại, vì AI cần giữ toàn bộ danh sách các công cụ có sẵn trong đầu. Nếu bạn có năm mươi hoặc một trăm công cụ, chúng chiếm không gian có thể được dùng cho lý luận thực tế. Còn có một vấn đề sâu hơn nữa: các công cụ không thể kết hợp. Bạn không thể kết hợp công cụ tìm kiếm và công cụ tính toán thành một thao tác linh hoạt duy nhất theo cách bạn có thể xâu chuỗi các lệnh trong bash.

Bash là đầu kia của phổ. Như đã thiết lập trong chương trước, bash cho tác nhân quyền truy cập vào toàn bộ hệ sinh thái phần mềm của máy nó đang chạy trên. Nó có thể kết hợp — bạn có thể xâu chuỗi các lệnh với nhau. Nó hiệu quả về bộ nhớ — AI không cần giữ danh sách các lệnh có thể trong đầu, vì nó có thể chạy --help trên bất kỳ chương trình nào để tìm hiểu những gì nó có thể làm ngay lập tức. Điều này có nghĩa là có chi phí độ trễ nhỏ: tác nhân dành một chút thời gian để tìm hiểu những công cụ nào có sẵn thay vì biết trước. Nhưng đổi lại, tác nhân có thể xử lý các tình huống mà nhà thiết kế của nó chưa bao giờ dự kiến. Nó có thể tìm kiếm, chuyển đổi, kết hợp và xác minh dữ liệu theo những cách mà không danh sách công cụ cố định nào có thể hỗ trợ.

Tạo code là tùy chọn mạnh mẽ nhất và tốn kém nhất. Thay vì gọi một hàm được định nghĩa trước hoặc chạy một lệnh một dòng, tác nhân viết toàn bộ chương trình — bằng Python, TypeScript hoặc bất kỳ ngôn ngữ nào phù hợp — và sau đó thực thi nó. Điều này cho phép logic cực kỳ động, linh hoạt: lặp qua hàng nghìn bản ghi, kết hợp dữ liệu từ nhiều API, thực hiện các phép tính thống kê, tạo biểu đồ. Sự đánh đổi là thời gian: viết và thực thi code mất nhiều thời gian hơn một lệnh gọi công cụ hoặc lệnh bash. Nó cũng có thể yêu cầu lint code được tạo ra trước để bắt lỗi trước khi chạy, và trong các ngôn ngữ biên dịch cần bước biên dịch. Nhưng khi nhiệm vụ thực sự phức tạp — xây dựng quy trình dữ liệu tùy chỉnh, chuyển đổi tập dữ liệu lộn xộn, tạo tài liệu được định dạng — tạo code là công cụ duy nhất đủ mạnh.

Tổng hợp của Thariq rất thực tế và rõ ràng. Sử dụng các công cụ được định nghĩa trước cho các hành động nguyên tử nơi bạn muốn tối đa kiểm soát và khả năng hiển thị. Trong Claude Code, thao tác ghi tệp là công cụ được định nghĩa trước — không phải lệnh bash — cụ thể vì Anthropic muốn người dùng thấy những gì sắp được viết và phê duyệt trước khi xảy ra. Bất kỳ hành động nào không thể đảo ngược (bạn không thể hoàn tác nó) hoặc hiển thị bên ngoài (nó gửi email, đăng tin nhắn, tính tiền thẻ tín dụng) nên là công cụ được định nghĩa trước, vì điều đó cho bạn điểm kiểm tra tự nhiên nơi con người có thể xem xét trước khi tiến hành. Sử dụng bash cho các thao tác có thể kết hợp, khám phá như tìm kiếm thư mục, grep qua nhật ký, quản lý tệp tạm hoặc kiểm tra xem điều gì đó có hoạt động không. Sử dụng tạo code cho các nhiệm vụ đòi hỏi tính linh hoạt và trí tuệ thực sự: kết hợp dữ liệu từ nhiều API, thực hiện phân tích hoặc tạo đầu ra phong phú như tài liệu được định dạng hay bảng điều khiển.

Một thành viên khán giả đặt câu hỏi thông minh tiếp theo: điều gì về việc ngăn chặn sự bùng nổ ngữ cảnh khi một lệnh gọi công cụ trả về lượng dữ liệu khổng lồ? Câu trả lời của Thariq đơn giản và thực tế: lưu đầu ra công cụ vào tệp ngay lập tức, và để công cụ chỉ trả về đường dẫn tệp. Bằng cách này kết quả lớn tồn tại trên đĩa thay vì trong cửa sổ ngữ cảnh. Tác nhân có thể đọc các phần cụ thể của nó sau khi cần, thay vì giữ tất cả trong bộ nhớ làm việc cùng một lúc.


VII. Kỹ Năng — Tiết Lộ Ngữ Cảnh Dần Dần

Kỹ năng là một trong những tính năng mới nhất của Claude Agent SDK — được phát hành chỉ hai tuần trước workshop này — và chúng đại diện cho một giải pháp thông minh cho một vấn đề chỉ trở nên rõ ràng khi bạn bắt đầu xây dựng các tác nhân phức tạp hơn.

Vấn đề là thế này: bạn không thể cung cấp cho tác nhân tất cả các hướng dẫn mà nó có thể cần ngay từ đầu. Nếu bạn cố gắng, những hướng dẫn đó sẽ tiêu thụ lượng lớn không gian cửa sổ ngữ cảnh, chiếm chỗ của công việc thực tế. Nhưng nếu bạn không cung cấp cho tác nhân đủ hướng dẫn, nó sẽ không biết cách xử lý các nhiệm vụ chuyên biệt. Làm thế nào để bạn cung cấp cho tác nhân chuyên môn chi tiết khi nó cần, mà không tải xuống mọi thứ ngay từ đầu?

Câu trả lời là tiết lộ ngữ cảnh dần dần — một cụm từ chỉ đơn giản có nghĩa là hiển thị cho tác nhân thêm thông tin dần dần khi nó trở nên liên quan. Kỹ năng là cách SDK thực hiện ý tưởng này. Một kỹ năng về cơ bản là một thư mục tệp nằm trên hệ thống tệp. Bên trong thư mục đó là các hướng dẫn chi tiết, ở cấp độ chuyên gia về cách làm điều gì đó cụ thể — cách tạo tệp DOCX được định dạng đúng cách, cách thực hiện thiết kế web front-end, cách gọi một API cụ thể một cách chính xác. Khi tác nhân gặp một nhiệm vụ đòi hỏi chuyên môn đó, nó đọc kỹ năng — nó "mở thư mục" và tải vào những hướng dẫn đó — và sau đó tiến hành với đầy đủ kiến thức về cách thực hiện công việc.

Thariq đưa ra một ví dụ sinh động về lý do tại sao điều này có giá trị. Anthropic gần đây đã phát hành kỹ năng thiết kế front-end. Nó được viết bởi một trong những kỹ sư AI giỏi nhất của Anthropic chuyên về thiết kế front-end, và nó mã hóa mọi thứ kỹ sư đó biết về việc tạo ra giao diện tốt: nguyên tắc bố cục, lựa chọn màu sắc, các mẫu thiết kế đáp ứng, cân nhắc về khả năng tiếp cận, cách cấu trúc HTML và CSS để tạo bằng AI. Kiến thức đó bây giờ tồn tại trong tệp kỹ năng, và bất kỳ tác nhân nào tải nó đều ngay lập tức có quyền truy cập vào cùng một chuyên môn. Kỹ năng là cách nắm bắt chuyên môn của con người ở dạng có thể truy xuất, có thể kết hợp.

Một thành viên khán giả đặt câu hỏi cấu trúc tốt: thứ tự ưu tiên là gì khi tệp kỹ năng và tệp CLAUDE.md chính đều chứa hướng dẫn? Câu trả lời thành thật của Thariq là chưa có thực tiễn tốt nhất rõ ràng — công nghệ còn quá mới. Mô hình tư duy hiện tại của ông là CLAUDE.md chứa các quy tắc thường trực luôn áp dụng, trong khi kỹ năng chứa chuyên môn theo tình huống mà tác nhân tải khi cần. Phép tương tự đúng có thể là sổ tay chính sách công ty (CLAUDE.md, luôn có hiệu lực) so với sổ tay chuyên gia mà một thành viên nhóm mở khi họ đảm nhận một loại dự án cụ thể (kỹ năng, được tải theo yêu cầu).

Ông cũng trả lời câu hỏi về việc liệu kỹ năng cuối cùng có được tích hợp vào chính mô hình hay không — có nghĩa là các mô hình AI tương lai sẽ chỉ biết cách làm tất cả những điều này mà không cần tệp hướng dẫn riêng biệt? Câu trả lời rộng rãi là có: khi các mô hình cải thiện, chúng sẽ xử lý nhiều nhiệm vụ hơn mà không cần hướng dẫn rõ ràng. Nhưng kỹ năng là giải pháp tốt nhất hiện tại cho các nhiệm vụ nằm ngoài những gì mô hình xử lý tự nhiên tốt. Thariq đưa ra một lời khuyên thẳng thắn và quan trọng: xem xét lại và viết lại code tác nhân của bạn mỗi sáu tháng, vì mô hình cơ bản sẽ thay đổi đủ để nhiều cách giải quyết và hướng dẫn rõ ràng bạn đã tích hợp có thể không còn cần thiết nữa, hoặc thậm chí có thể cản trở khả năng gốc được cải thiện của mô hình. Các tác nhân tốt nhất là các tác nhân gọn nhẹ tin tưởng mô hình làm những gì nó giỏi và chỉ thêm hướng dẫn rõ ràng nơi thực sự có khoảng trống.


VIII. Bảo Mật và Quyền Hạn — Phòng Thủ Phô Mai Thụy Sĩ

Một thành viên khán giả đặt ra điều mà có lẽ là mối lo ngại rõ ràng nhất về toàn bộ triết lý bash-first: nếu tác nhân có thể chạy bất kỳ lệnh nào trên máy tính, điều gì ngăn kẻ xấu chiếm đoạt nó? Đây là một câu hỏi hợp lý và nghiêm trọng, và câu trả lời của Thariq giới thiệu một khuôn khổ gọi là phòng thủ phô mai Thụy Sĩ.

Phòng thủ phô mai Thụy Sĩ là một khái niệm kinh điển từ kỹ thuật an toàn. Hãy tưởng tượng một chồng các lát phô mai Thụy Sĩ, mỗi lát đầy lỗ hổng. Không có lát nào đặc hoàn toàn — mỗi lát đều có điểm yếu. Nhưng khi bạn xếp đủ lát lại với nhau, các lỗ hiếm khi thẳng hàng và cùng nhau chúng chặn hầu hết mọi thứ đi qua. Bảo mật trong một hệ thống phức tạp hoạt động theo cùng một cách: không có lớp nào hoàn hảo, nhưng nhiều lớp không hoàn hảo cùng nhau tạo ra bảo vệ hiệu quả.

Đối với Claude Agent SDK, các lớp hoạt động như sau. Ở lớp mô hình — bên trong chính AI — Anthropic thực hiện công việc căn chỉnh rộng rãi. Căn chỉnh là quá trình huấn luyện AI hành xử theo những cách an toàn và có lợi, từ chối các yêu cầu có hại và gắn cờ các hướng dẫn đáng ngờ. Mô hình đã được dạy để nhận ra khi nào nó đang bị thao túng để làm điều gì đó nguy hiểm. Ở lớp khung hỗ trợ — cơ sở hạ tầng phần mềm xung quanh mô hình — SDK bao gồm hệ thống cấp quyền riêng và các lệnh nhắc an toàn của nó. Một cách quan trọng, nó chạy bộ phân tích cú pháp (parser) trên mọi lệnh bash mà tác nhân cố gắng thực thi. Bộ phân tích cú pháp là một chương trình đọc và diễn giải code hoặc lệnh để hiểu những gì chúng thực sự làm. Vì SDK phân tích cú pháp các lệnh bash, nó có thể phát hiện các mẫu đáng ngờ — như nỗ lực xóa các tệp hệ thống hoặc gửi dữ liệu đến máy chủ không xác định — trước khi chúng xảy ra. Thariq nhấn mạnh rằng bộ phân tích cú pháp này không phải là thứ bạn muốn tự xây dựng; đó là một trong những tính năng an toàn có giá trị nhất của SDK.

Lớp thứ ba là sandboxing (hộp cát). Sandbox là môi trường chứa, cô lập nơi code có thể chạy mà không ảnh hưởng đến bất cứ điều gì bên ngoài các bức tường của nó. Nếu một tác nhân bị xâm phạm chạy trong sandbox với quyền truy cập mạng bị hạn chế và không có quyền truy cập vào các tệp ngoài thư mục được chỉ định của nó, thiệt hại mà nó có thể gây ra bị hạn chế nghiêm trọng. Thariq mô tả điều ông gọi là "bộ ba chết chóc" của các rủi ro bảo mật tác nhân: khả năng thực thi code, khả năng sửa đổi hệ thống tệp và khả năng đánh cắp dữ liệu — tức là bí mật sao chép và gửi dữ liệu đó đến máy chủ bên ngoài. Nếu bạn sandbox kết nối mạng để tác nhân không thể thực hiện yêu cầu đi ra ngoài đến các máy chủ tùy ý, chân thứ ba của bộ ba đó bị cắt đứt, và một cuộc tấn công thành công trở nên ít nguy hiểm hơn nhiều.

Thariq cũng đề cập đến kiểm soát truy cập dựa trên vai trò — thực hành cấp cho người dùng hoặc dịch vụ khác nhau các mức quyền khác nhau. Khuyến nghị của ông là xử lý điều này ở cấp độ cơ sở hạ tầng, không phải bên trong chính tác nhân. Bạn cung cấp khóa API (thông tin xác thực truy cập) được giới hạn chỉ trong các thao tác cần thiết. Bạn có thể tạo các máy chủ proxy ngăn chặn các yêu cầu API và thực thi chính sách trước khi chúng đến dịch vụ cơ bản. Và bạn có thể tận dụng sự nhạy cảm của mô hình đối với phản hồi: nếu backend của bạn ném ra thông báo lỗi — "quyền bị từ chối khi truy cập bản ghi này" — tác nhân sẽ đọc lỗi đó, hiểu nó và ngừng thử. Khả năng tích hợp của mô hình để đọc và phản hồi các thông báo lỗi tự nó là một cơ chế bảo mật có thể được thiết kế một cách có chủ ý.


IX. Demo Trực Tiếp — Tác Nhân Pokémon

Để làm cho mọi thứ trở nên cụ thể, Thariq xây dựng một tác nhân trực tiếp từ đầu trong workshop. Ông chọn Pokémon làm miền chủ đề một cách cố ý — nó có API lớn, có sẵn công khai (giao diện web để yêu cầu dữ liệu theo chương trình) với hàng nghìn bản ghi và các mối quan hệ phức tạp, mô phỏng loại nguồn dữ liệu lộn xộn trong thế giới thực mà khán giả của ông phải đối mặt trong kinh doanh của họ. Và vì ông không phải là chuyên gia về Pokémon thi đấu, tác nhân phải thực sự tìm hiểu thay vì chỉ xác nhận những gì Thariq đã biết.

Bước đầu tiên của ông là để Claude Code — trợ lý lập trình AI — xây dựng thư viện cho ông. Ông đưa cho nó một lệnh nhắc đơn giản: "Tìm kiếm PokéAPI, hiểu cách nó hoạt động và tạo một thư viện TypeScript bọc nó lại." TypeScript là ngôn ngữ lập trình thường được sử dụng cho các ứng dụng web. Thư viện, trong lập trình, là tập hợp các hàm được xây dựng sẵn giúp một nhiệm vụ phức tạp trở nên dễ dàng hơn — trong trường hợp này, thay vì tác nhân phải tìm hiểu API thô mỗi lần, nó có thể gọi một hàm sạch như getByName("pikachu") và nhận lại kết quả có cấu trúc. Claude Code khám phá API, đọc tài liệu của nó và tạo ra một thư viện với các hàm để tìm nạp Pokémon theo tên, liệt kê tất cả Pokémon, lấy chi tiết loài, tra cứu khả năng và nhiều thứ khác.

Sau đó đến phần quan trọng: Claude Code cũng tạo ra tệp CLAUDE.md cho dự án cụ thể này. CLAUDE.md này nói với tác nhân Pokémon các quy tắc của môi trường của nó — cụ thể, rằng nó nên sử dụng thư viện TypeScript này, rằng nó nên viết các script có thể thực thi trong thư mục examples để trả lời các truy vấn thay vì chỉ trả lời từ bộ nhớ, và rằng nó nên chạy những script đó và sử dụng dữ liệu thực tế. Tệp CLAUDE.md đó, kết hợp với thư viện TypeScript, về cơ bản là toàn bộ thiết kế tác nhân. Không có code điều phối phức tạp. Chỉ có một tệp hướng dẫn rõ ràng và một bộ công cụ gọn gàng. Đây là điều Thariq muốn nói khi ông nói về kỹ thuật ngữ cảnh: hành vi của tác nhân được hình thành chủ yếu bởi những gì có trong tệp hướng dẫn và những công cụ nào có sẵn cho nó, không phải bởi logic phức tạp trong code xung quanh.

Sau đó ông trình diễn sự khác biệt giữa cách tiếp cận bash-và-tạo-code và cách tiếp cận chỉ sử dụng công cụ truyền thống. Đối với phiên bản chỉ sử dụng công cụ, ông đã định nghĩa trước năm hàm: getPokemon, getPokemonSpecies, getPokemonAbility, getPokemonTypegetMove. Khi người dùng hỏi "các Pokémon nước thế hệ 2 là gì?" phiên bản chỉ sử dụng công cụ gặp khó khăn — truy vấn cụ thể đó đòi hỏi phải lặp qua hàng trăm Pokémon và lọc theo cả thế hệ lẫn loại, đây không phải là điều mà bất kỳ công cụ nào trong năm công cụ được định nghĩa trước được xây dựng để làm. Phiên bản bash-và-tạo-code, ngược lại, viết một script, lặp qua danh sách Pokémon của PokéAPI, kiểm tra loại và thế hệ của từng cái và trả về kết quả đã lọc. Nó xử lý một truy vấn chưa bao giờ được dự kiến trong thiết kế ban đầu.

Phần ấn tượng nhất của demo liên quan đến phân tích Pokémon thi đấu sử dụng dữ liệu từ Smogon, một cơ sở dữ liệu trực tuyến lớn về chiến lược Pokémon thi đấu. Dữ liệu này không có sẵn qua PokéAPI — Thariq chỉ đơn giản tải xuống một tệp văn bản Smogon và đặt nó vào thư mục dữ liệu của dự án. Không có phân tích cú pháp đặc biệt, không có cơ sở dữ liệu có cấu trúc, chỉ là tệp văn bản thô. Khi được hỏi "Tôi muốn xây dựng đội dựa trên Venusaur — hãy đưa cho tôi gợi ý dựa trên dữ liệu Smogon," tác nhân bắt đầu grep qua tệp văn bản. Nó tìm thấy hồ sơ của Venusaur, sau đó tìm kiếm các Pokémon khác đề cập đến Venusaur như là lựa chọn hỗ trợ, chạy script để đếm tần suất các đối tác khác nhau xuất hiện cùng nhau và tập hợp đề xuất đội đầy đủ. Tác nhân không cần API Smogon. Nó cần bash và một tệp văn bản. Đó là sức mạnh của cách tiếp cận: tác nhân đã tìm ra cách trích xuất thông tin chi tiết có cấu trúc từ dữ liệu phi cấu trúc, sử dụng các công cụ đã tồn tại hàng thập kỷ.


X. Bài Tập Tác Nhân Bảng Tính

Thay vì chỉ trình diễn tác nhân của mình, Thariq biến workshop thành tương tác bằng cách yêu cầu khán giả cùng suy nghĩ về tác nhân bảng tính. Tác nhân bảng tính là trường hợp sử dụng thực tế, dễ hiểu — hầu hết các doanh nghiệp vận hành trên bảng tính — và nó minh họa vòng lặp tác nhân ba giai đoạn (thu thập ngữ cảnh, thực hiện hành động, xác minh) trong một miền mà mọi người đều hiểu.

Câu hỏi đầu tiên là: tác nhân tìm kiếm bảng tính như thế nào? Bảng tính là cấu trúc hai chiều — hàng và cột — điều này làm cho nó phức tạp hơn so với việc tìm kiếm tệp văn bản phẳng. Khán giả suy nghĩ. Ai đó gợi ý chuyển đổi tệp sang định dạng CSV (định dạng văn bản thuần túy nơi các giá trị được phân cách bằng dấu phẩy) và sử dụng grep. Khởi đầu tốt — tác nhân có thể nhanh chóng quét để tìm từ khóa. Nhưng Thariq chỉ ra giới hạn: nếu người dùng hỏi "tổng doanh thu năm 2026 là bao nhiêu?" tác nhân cần tìm cột doanh thu và sau đó lọc hàng theo năm. Chỉ có tiêu đề cột, được khám phá bằng grep, không cho bạn biết hàng nào tương ứng với năm 2026.

Gợi ý khác: sử dụng AWK, lệnh Unix cũ và mạnh mẽ để xử lý các tệp văn bản có cấu trúc. AWK có thể khớp các mẫu trong các cột cụ thể và thực hiện số học kịp thời, làm cho nó có năng lực đáng kể hơn grep cho dữ liệu dạng bảng. Sau đó ai đó đề xuất giải pháp thanh lịch nhất: tải CSV vào SQLite và truy vấn nó bằng SQL. SQLite là một công cụ cơ sở dữ liệu nhẹ có thể chạy hoàn toàn trên một tệp duy nhất — không cần máy chủ. SQL là ngôn ngữ tiêu chuẩn để truy vấn dữ liệu có cấu trúc, và các mô hình AI được huấn luyện vô cùng tốt trên SQL vì có rất nhiều SQL trên internet. Thariq sáng lên khi nghe gợi ý này: nếu bạn có thể dịch nguồn dữ liệu của mình thành giao diện SQL, tác nhân có thể truy vấn nó với độ chính xác cao và xử lý hầu hết mọi câu hỏi mà người dùng có thể đặt ra. Bước chuyển đổi đó — chuyển đổi nguồn dữ liệu lộn xộn thành thứ gì đó có thể truy vấn được — là một trong những cách tiếp cận kiến trúc mạnh mẽ nhất bạn có thể thực hiện khi thiết kế giao diện dữ liệu tác nhân.

Cách tiếp cận thứ tư xuất hiện khi Thariq nhắc nhở khán giả rằng các tệp XLSX — định dạng Excel tiêu chuẩn — thực sự là các tệp ZIP chứa các tệp XML. XML là định dạng văn bản có cấu trúc, và bạn có thể chạy các truy vấn dựa trên đường dẫn trực tiếp trên nó, hoặc sử dụng các thư viện hiểu định dạng Excel gốc. Vì vậy, bạn có ít nhất bốn cách tiếp cận cho tác nhân bảng tính: grep trên tiêu đề, AWK cho việc lọc cấp độ hàng, wrapper SQLite hoặc truy vấn đường dẫn XML. Lời khuyên của Thariq: đừng dừng lại ở cách tiếp cận đầu tiên hoạt động. Thử nhiều chiến lược, chạy các bài kiểm thử, xem các bản ghi tác nhân đang chạy của bạn và xem cách nào nó xử lý tốt nhất.

Đối với giai đoạn hành động — thực hiện thay đổi đối với bảng tính — các giao diện trông rất giống với các giao diện tìm kiếm. Chèn một hàng trông giống như viết mảng hai chiều. Chạy SQL UPDATE sửa đổi các bản ghi. Chỉnh sửa XML cơ bản hoạt động cho cả đọc và ghi. Tính đối xứng giữa đọc và ghi là một nguyên tắc thiết kế hữu ích: nếu bạn xây dựng giao diện tìm kiếm tốt, bạn có thể đã có hầu hết những gì bạn cần cho giao diện hành động.

Xác minh cho tác nhân bảng tính đòi hỏi sự chú ý cụ thể. Tác nhân nên kiểm tra các giá trị null — ô trống nơi dữ liệu được mong đợi. Nó nên tìm kiếm các bất thường, như ô thay đổi bất ngờ hoặc tổng không cộng lại đúng. Một mẫu mạnh mẽ mà Thariq mô tả là tác nhân phụ đối kháng: sau khi tác nhân chính hoàn thành công việc, khởi tạo tác nhân thứ hai không biết gì về những gì tác nhân đầu tiên đã làm, cho nó thấy đầu ra và yêu cầu nó phê bình kết quả. Vì tác nhân thứ hai không gắn bó với công việc, nó sẽ nhận thấy những điểm không nhất quán và lỗi mà tác nhân đầu tiên có thể đã hợp lý hóa. Khi lý luận AI cải thiện, bước xác minh đối kháng này trở nên ngày càng đáng tin cậy hơn.

Một thành viên khán giả đặt ra vấn đề quan trọng về khả năng đảo ngược — điều gì xảy ra nếu tác nhân xóa toàn bộ bảng tính? Thariq coi đây là câu hỏi thiết kế cơ bản, không chỉ là câu hỏi kỹ thuật. Miền bạn đang xây dựng có thể đảo ngược như thế nào? Code có thể đảo ngược cao vì mọi thay đổi được git theo dõi, một hệ thống kiểm soát phiên bản ghi lại lịch sử đầy đủ của mọi sửa đổi. Claude Code sử dụng git liên tục — Thariq đề cập rằng ông không còn tự gõ lệnh git nữa; tác nhân xử lý chúng. Các tác nhân sử dụng máy tính nhấp xung quanh giao diện đồ họa gần như không thể đảo ngược, vì mỗi nhấp chuột làm tăng thêm trạng thái. Tác nhân bảng tính nằm ở giữa. Khuyến nghị của ông: thiết kế khả năng đảo ngược từ đầu. Lưu trữ các điểm kiểm tra trạng thái để nếu có điều gì đó không ổn, người dùng có thể nói "quay lại trước thay đổi đó." Ông đề cập rằng ai đó đã xây dựng công cụ "du hành thời gian" cho tác nhân lập trình cho phép chính xác loại khôi phục này. Nguyên tắc cơ bản — rằng các tác nhân nên có thể hoàn tác hành động của họ, ít nhất cho các thao tác quan trọng — áp dụng cho bất kỳ miền nào có thể xảy ra sai sót, tức là mọi miền.


XI. Tác Nhân Phụ và Quản Lý Ngữ Cảnh

Một thành viên khán giả đặt câu hỏi đến gần một trong những hạn chế thực tế quan trọng nhất của các tác nhân AI: "Tất cả các tác nhân có chia sẻ cùng cửa sổ ngữ cảnh không?" Câu trả lời dẫn Thariq vào một trong những phần thú vị nhất về mặt kỹ thuật của workshop.

Để nhắc lại cửa sổ ngữ cảnh là gì: đó là bộ nhớ làm việc của AI. Mọi thứ tác nhân đang "suy nghĩ về" hiện tại — hướng dẫn của nó, lịch sử cuộc hội thoại, kết quả của các lệnh gọi công cụ, các tệp nó đã đọc, code nó đã viết — phải vừa trong cửa sổ này. Hầu hết các mô hình AI hiện tại có cửa sổ ngữ cảnh được đo bằng hàng trăm nghìn token (một token xấp xỉ một từ hoặc một vài ký tự). Điều đó nghe có vẻ lớn, nhưng một tác nhân chạy lâu có thể tiêu thụ nó nhanh chóng: đọc một trăm tệp, chạy hàng chục script, xem lại đầu ra của từng cái và bạn đã tiêu thụ một lượng bộ nhớ khổng lồ. Khi cửa sổ ngữ cảnh đầy, tác nhân mất suy nghĩ trước đó của mình trừ khi có điều gì đó được làm để bảo toàn các phần quan trọng.

Các tác nhân phụ là một trong những công cụ quan trọng nhất để quản lý ngữ cảnh. Tác nhân phụ đơn giản là một phiên bản AI mới mà tác nhân chính tạo ra để xử lý một nhiệm vụ con cụ thể. Tác nhân phụ bắt đầu với cửa sổ ngữ cảnh sạch, thực hiện công việc của nó và chỉ trả về câu trả lời — một bản tóm tắt chắt lọc về những gì nó tìm thấy — cho tác nhân chính. Tác nhân chính không bao giờ phải giữ tất cả những suy nghĩ khám phá, đang tiến hành của nhiệm vụ con trong bộ nhớ của chính nó. Nó chỉ nhận kết quả.

Thariq đưa ra ví dụ bảng tính: nếu bạn có một sổ làm việc với ba trang và cần phân tích cả ba, tác nhân chính có thể tạo ra ba tác nhân phụ song song — một cho mỗi trang. Mỗi tác nhân phụ đọc trang của nó đầy đủ, suy luận trên nó và trả về một bản tóm tắt. Tác nhân chính sau đó suy luận trên ba bản tóm tắt thay vì ba trang đầy đủ. Công việc khám phá tốn kém được phân phối; tác nhân chính vẫn gọn nhẹ. Chạy các tác nhân phụ song song có nghĩa là tất cả ba có thể làm việc đồng thời, điều này cũng giảm tổng thời gian.

Điều này nghe có vẻ đơn giản, nhưng Thariq chỉ ra rằng các tác nhân phụ song song với quyền truy cập bash thực sự là một trong những vấn đề kỹ thuật khó khăn hơn trong thiết kế tác nhân. Race conditions — tình huống mà hai tiến trình cố gắng đọc hoặc ghi cùng một tệp tại cùng một thời điểm và tạo ra kết quả bị hỏng — là rủi ro thực sự. Xung đột hệ thống tệp đòi hỏi điều phối cẩn thận. Claude Agent SDK xử lý sự phức tạp này nội bộ, sử dụng kiến trúc được mượn trực tiếp từ việc triển khai đa tác nhân của Claude Code. Thariq nói ông chưa thấy framework nào khác xử lý các tác nhân phụ bash song song một cách mạnh mẽ như vậy.

Quản lý ngữ cảnh cũng có chiều hướng trải nghiệm người dùng trực tiếp. Thariq quan sát rằng khi ông nói chuyện với những người dùng Claude Code nâng cao, một số trong số họ đề cập đến việc đang ở "compact thứ năm." Nén (compaction), còn gọi là nén ngữ cảnh, là quá trình tóm tắt các phần cũ hơn của cuộc hội thoại để giải phóng chỗ cho công việc mới. Bản tóm tắt thay thế lịch sử đầy đủ, bảo tồn các sự kiện chính trong khi loại bỏ những trao đổi chi tiết. Thariq bản thân nói ông hiếm khi nén — đối với công việc lập trình, trạng thái tồn tại trong các tệp của codebase, không phải trong lịch sử chat. Nếu ông hoàn thành một nhiệm vụ và bắt đầu nhiệm vụ mới, Claude Code có thể nhìn vào git diff (tóm tắt những gì đã thay đổi trong code) và hiểu trạng thái hiện tại mà không cần toàn bộ lịch sử cuộc hội thoại.

Đối với các tác nhân được triển khai cho người dùng không chuyên kỹ thuật — tác nhân dịch vụ khách hàng, trợ lý bảng tính — thách thức quản lý ngữ cảnh phức tạp hơn, vì người dùng không hiểu khái niệm cửa sổ ngữ cảnh và không nên cần phải hiểu. Thách thức thiết kế trải nghiệm người dùng là: bạn có thể đặt lại hoặc nén trạng thái cuộc hội thoại một cách khéo léo mà người dùng không nhận thấy không? Trong tác nhân bảng tính, hầu hết trạng thái nằm trong chính bảng tính, không phải trong lịch sử cuộc hội thoại, vì vậy tác nhân có thể không cần mang nhiều thứ qua các lượt. Lưu trữ sở thích người dùng vào tệp khi chúng được diễn đạt — để tác nhân nhớ chúng trong các phiên tương lai mà không cần bản ghi đầy đủ — là một cách tiếp cận thực tế. Mục tiêu cơ bản là giảm thiểu sử dụng ngữ cảnh mà không làm giảm trải nghiệm của người dùng.


XII. Móc Nối — Xác Minh Xác Định

Một thành viên khán giả hỏi về hooks, và Thariq nói ông chưa nói về chúng đủ nhiều. Hooks là một trong những tính năng bị đánh giá thấp nhất trong SDK, và chúng giải quyết một vấn đề trở nên rất rõ ràng khi tác nhân của bạn đang chạy trong thế giới thực: tác nhân có tính xác suất, có nghĩa là nó không luôn hành xử theo cùng một cách, nhưng đôi khi bạn cần một số thứ xảy ra với sự chắc chắn tuyệt đối.

Một hook là một đoạn code thực thi tự động tại một thời điểm cụ thể trong hoạt động của tác nhân — trước lệnh gọi công cụ, sau lệnh gọi công cụ, khi một phản hồi được tạo ra. Bạn đăng ký trình xử lý hook trong SDK, và mỗi khi sự kiện đó kích hoạt, trình xử lý của bạn chạy. Không giống như lý luận của chính AI — linh hoạt và đôi khi không thể đoán trước — hooks là xác định. Chúng luôn chạy. Chúng luôn làm chính xác những gì bạn đã lập trình chúng làm.

Thariq đưa ra một số ví dụ làm cho khái niệm này trở nên cụ thể ngay lập tức. Giả sử bạn có tác nhân bảng tính và bạn muốn chạy kiểm tra xác thực sau mỗi thay đổi mà tác nhân thực hiện — xác nhận rằng các tổng vẫn cộng lại, rằng không có ô bắt buộc nào trống, rằng các giá trị nằm trong phạm vi mong đợi. Bạn đăng ký một hook kích hoạt sau mỗi lệnh gọi công cụ và chạy xác thực đó. Tác nhân không thể bỏ qua nó. Nó chạy mỗi lần, dù tác nhân vừa làm gì. Một ví dụ khác: người dùng đang chỉnh sửa bảng tính trong thời gian thực trong khi tác nhân cũng đang làm việc trên nó. Một hook có thể phát hiện rằng tệp đã thay đổi từ bên ngoài, tạm dừng tác nhân và đưa tin nhắn vào ngữ cảnh nói "người dùng đã sửa đổi cột C — vui lòng đọc lại trạng thái hiện tại trước khi tiếp tục." Tác nhân nhận được cập nhật trực tiếp về môi trường của nó mà không cần liên tục kiểm tra.

Hooks cũng giải quyết một trong các chế độ lỗi cụ thể mà Thariq quan sát trong demo Pokémon của mình. Miền Pokémon là thứ mà các kỹ sư gọi là "in-distribution" đối với mô hình — có nghĩa là mô hình được huấn luyện trên rất nhiều dữ liệu Pokémon và có nhiều sự kiện được ghi nhớ. Đôi khi tác nhân sẽ chỉ đơn giản trả lời từ bộ nhớ thay vì chạy script để kiểm tra dữ liệu thực tế. Đây là vấn đề vì tác nhân có thể trả lời dựa trên dữ liệu huấn luyện cũ, không phải tệp Smogon cập nhật trên đĩa. Một hook có thể ngăn chặn phản hồi trước khi đến người dùng, kiểm tra xem phản hồi có dựa trên việc thực thi script thực tế không, và nếu không, đưa phản hồi vào: "Vui lòng đảm bảo bạn đã viết script và đọc từ tệp dữ liệu thực tế." Tác nhân nhận phản hồi đó, xem xét lại cách tiếp cận của mình và thử lại. Đây là hành vi xác định được áp đặt lên trên lý luận xác suất — và đó là giải pháp đáng tin cậy hơn nhiều so với việc cố gắng ngăn hành vi thông qua kỹ thuật lệnh nhắc đơn thuần.

Thariq chỉ đến việc Claude Code sử dụng hooks như một minh họa. Claude Code kích hoạt hook bất cứ khi nào tác nhân cố gắng ghi vào tệp mà nó chưa đọc. Hook ném ra lỗi: "Bạn chưa đọc tệp này. Hãy thử đọc nó trước." Điều này ngăn một lỗi phổ biến và tốn kém — tác nhân ghi đè lên tệp dựa trên các giả định thay vì kiến thức thực tế về nội dung hiện tại của nó. Một quy tắc xác định đó tiết kiệm vô số giờ gỡ lỗi các ghi đè không chính xác. Hooks, theo nghĩa này, là cơ chế mà bạn có thể lấy những thực tiễn tốt nhất bạn phát hiện qua quan sát và đưa chúng vào hệ thống một cách cứng rắn để chúng luôn được thực thi, bất kể mô hình đang cảm thấy thế nào trong bất kỳ phiên nào.


XIII. Hỏi & Đáp — Mở Rộng Quy Mô, Tái Tạo và Thế Giới Thực

Phần cuối của workshop mở ra thành phiên hỏi đáp bao gồm các câu hỏi thực tế mà bất kỳ lập trình viên hay doanh nhân nào sẽ phải đối mặt khi họ chuyển từ workshop sang thực sự vận chuyển sản phẩm. Các câu hỏi tiết lộ khoảng cách giữa sự thanh lịch lý thuyết của kiến trúc tác nhân và thực tế lộn xộn của các hệ thống sản xuất.

Từ Nguyên Mẫu Đến Sản Xuất

Câu hỏi đầu tiên là cơ bản nhất: bạn đã xây dựng nguyên mẫu hoạt động. Bây giờ làm thế nào để bạn làm cho nó có thể tái tạo và đáng tin cậy? Câu trả lời của Thariq bắt đầu với CLAUDE.md. Tệp hướng dẫn là nơi quan trọng nhất để mã hóa những gì bạn học được trong quá trình tạo nguyên mẫu. Trong demo Pokémon của ông, tác nhân đã bỏ qua thư viện TypeScript được xây dựng trước của ông trong một lần chạy và viết JavaScript thuần túy thay thế. Điều đó xảy ra vì CLAUDE.md không nói rõ ràng "bạn phải sử dụng thư viện này." Bài học: bất cứ điều gì tác nhân làm sai trong nguyên mẫu của bạn do hướng dẫn không rõ ràng nên được sửa bằng cách thêm quy tắc rõ ràng, cụ thể vào CLAUDE.md. Tệp hướng dẫn nên phát triển khi bạn phát hiện ra các trường hợp ngoại lệ, không chỉ đóng vai trò giới thiệu mơ hồ.

Phần thứ hai của câu trả lời là các script trợ lý. Khi bạn tìm thấy một cách tiếp cận hoạt động — chẳng hạn, tải CSV vào SQLite và truy vấn nó — hãy viết script thực hiện thiết lập đó và ghi chú trong CLAUDE.md rằng script tồn tại và khi nào sử dụng nó. Các script trợ lý tốt phục vụ hai mục đích: chúng cung cấp cho tác nhân một con đường nhanh, đáng tin cậy đến cách tiếp cận đúng, và chúng ghi lại những gì bạn học được trong quá trình tạo nguyên mẫu để các tác nhân tương lai (và phiên bản tương lai của chính bạn) có thể hưởng lợi từ nó.

Khi Tác Nhân Gian Lận

Một thành viên khán giả mô tả trải nghiệm điên rồ: tác nhân Pokémon của họ cố chạy script, thất bại vài lần, và sau đó chỉ đơn giản trả về bảng thống kê Pokémon từ bộ nhớ. Tác nhân đã ngừng cố gắng sử dụng dữ liệu thực tế và bắt đầu bịa đặt từ dữ liệu huấn luyện của mình. Thariq thừa nhận đây là thách thức thực sự. Dữ liệu huấn luyện của mô hình là kiến thức nền tảng của nó, và đối với các miền phổ biến như Pokémon — hoặc các chủ đề kinh doanh thông thường — kiến thức nền tảng đó thường đủ gần với đúng để mô hình đi đường tắt. Điều này được gọi là "in-distribution": nhiệm vụ quá giống với những gì mô hình đã thấy trước đây đến mức nó không cảm thấy cần phải đi tra cứu.

Giải pháp mà Thariq khuyến nghị là hooks, như đã thảo luận trong chương trước. Bạn viết một hook ngăn chặn mọi phản hồi trước khi đến người dùng và kiểm tra bằng chứng rằng tác nhân thực sự đã chạy script. Nếu không có script nào được chạy, hook đưa phản hồi vào: "Bạn phải viết script và sử dụng dữ liệu thực tế. Đừng trả lời từ bộ nhớ." Đây là rào chắn xác định làm cho việc gian lận trở nên không thể thay vì chỉ khó có thể xảy ra. Không có lượng lệnh nhắc nào một mình có thể ngăn hành vi này một cách đáng tin cậy — mô hình đôi khi sẽ bỏ qua các hướng dẫn khi sự tự tin vào kiến thức của chính nó cao. Hook không thể bị bỏ qua.

Codebase Khổng Lồ

Một lập trình viên đặt ra vấn đề thực tế đáng lo ngại: họ đang làm việc với codebase hơn năm mươi triệu dòng code. Các công cụ tiêu chuẩn như grep trở nên chậm đau đớn ở quy mô đó. Họ đang xây dựng hệ thống lập chỉ mục ngữ nghĩa của riêng họ — hệ thống tìm kiếm tìm code dựa trên ý nghĩa thay vì chỉ khớp văn bản chính xác — và họ muốn biết liệu Anthropic có kế hoạch làm điều gì đó như vậy thành gốc trong SDK không.

Thariq đưa ra câu trả lời thẳng thắn, hai phần. Đầu tiên, phần trung thực: có, bất cứ điều gì bạn xây dựng cho vấn đề này hôm nay có thể sẽ bị làm lỗi thời bởi những cải tiến trong các công cụ trong sáu đến mười hai tháng tới. Lĩnh vực đang di chuyển đủ nhanh để cơ sở hạ tầng tùy chỉnh được xây dựng để bù đắp cho các hạn chế hiện tại thường trở nên không cần thiết. Thứ hai, phần thực tế: Anthropic không sử dụng lập chỉ mục ngữ nghĩa cho chính Claude Code. Thay vào đó, họ dựa vào các tệp CLAUDE.md được cấu trúc tốt cho biết tác nhân biết mọi thứ tồn tại ở đâu trong codebase — thư mục nào chứa loại code nào, quy ước đặt tên là gì — để tác nhân có thể điều hướng hiệu quả mà không cần tìm kiếm mọi thứ. Và họ thường khởi động tác nhân trong một thư mục con cụ thể có liên quan đến nhiệm vụ, thay vì thả nó ở thư mục gốc của kho tài nguyên năm mươi triệu dòng và mong nó tìm đường. Kỹ thuật ngữ cảnh tốt — cho tác nhân biết nơi cần tìm — thường vượt trội so với cơ sở hạ tầng tìm kiếm phức tạp. Tuy nhiên, Thariq cẩn thận không tuyên bố điều này giải quyết hoàn toàn vấn đề. Đối với các codebase thực sự khổng lồ, vẫn còn lãnh thổ chưa được khám phá.

Kiếm Tiền

Câu hỏi cuối cùng là về tiền bạc. Các tác nhân rất tốn kém để chạy — họ thực hiện nhiều lệnh gọi API, họ chạy lâu và chi phí mỗi nhiệm vụ có thể đáng kể. Với tất cả chi phí chảy về Anthropic, làm thế nào các lập trình viên phải xây dựng một doanh nghiệp khả thi?

Câu trả lời của Thariq là lời khuyên kinh doanh phần mềm cổ điển được áp dụng vào bối cảnh mới: tìm những vấn đề thực sự khó khăn và thực sự có giá trị, và tính phí phù hợp. Kinh tế học của các tác nhân hoạt động khi vấn đề chúng giải quyết đủ tốn kém để chi phí mỗi nhiệm vụ là một món hời. Nếu một tác nhân tiết kiệm cho một luật sư bốn giờ xem xét tài liệu, tính hai mươi đô la cho nhiệm vụ đó không chỉ khả thi — đó là rẻ mạt. Thất bại đến từ việc cố gắng tính những khoản tiền nhỏ cho các nhiệm vụ không đủ có giá trị để biện minh cho chi phí. Về cơ cấu giá, Thariq lưu ý rằng Claude Code sử dụng mô hình kết hợp: đăng ký hàng tháng cố định cho việc sử dụng tiêu chuẩn, với giá dựa trên sử dụng cho người dùng nặng vượt quá giới hạn. Điều này cân bằng tính có thể đoán trước (người dùng biết đại khái họ sẽ trả bao nhiêu) với sự công bằng (người dùng nặng trả nhiều hơn). Ông khuyến nghị nghĩ về cơ cấu giá từ sớm, vì việc thay đổi sau khi người dùng đã quen với một mô hình cụ thể khó khăn hơn nhiều.

Workshop kết thúc bằng tiếng vỗ tay. Thông điệp trung tâm của Thariq — rằng kiến trúc đúng đắn cho các tác nhân AI là triết lý Unix về các công cụ có thể kết hợp, ưu tiên tệp, được hỗ trợ bởi bash — ban đầu có thể cảm thấy không trực quan. Nó có vẻ quá đơn giản, quá lỗi thời, quá phụ thuộc vào công nghệ có trước AI hàng thập kỷ. Nhưng đó chính xác là điểm mấu chốt. Những công cụ bền vững nhất là những công cụ đã tồn tại lâu nhất. Hệ thống tệp và dòng lệnh đã tồn tại vì chúng thực sự là mục đích chung. Việc cho AI quyền truy cập vào chúng không hạn chế những gì AI có thể làm — nó khuếch đại nó.