메뉴
HN
Hacker News 15일 전

AI 에이전트를 위한 API 설계 방법

IMP
9/10
핵심 요약

인간이 아닌 AI 에이전트가 API의 주요 소비자로 부상함에 따라, API 설계 패러다임이 완전히 뒤바뀌고 있습니다. 인간의 인지 능력을 돕던 기존의 친절한 기본값이나 유연한 에러 처리 방식은 버그를 유발하므로, 에이전트를 위해서는 모든 값을 명시하고 엄격하게 에러를 반환하는 것이 중요해졌습니다.

번역된 본문

에이전트를 위한 API를 설계하는 것은 인간을 위해 설계하는 것과 다릅니다. 오늘날 대부분의 API 소비자는 에이전트가 작성한 코드를 통해 이루어집니다. 이는 2년 전만 해도 사실이 아니었으며, 우리가 API를 설계하는 방식에 대한 생각을 바꿔놓았습니다. 나는 이제 인간을 위해 만들어진 대부분의 시스템을 더 이상 믿지 않습니다. 나는 대부분의 패키지를 의심하고, 유틸리티 함수에 반대하며, 이제는 지나치게 긴 이름을 지지합니다. 이 모든 것은 지난 24개월 동안 내가 완전히 180도 입장을 바꾼 의견들입니다.

인간을 위한 좋은 API 내가 인간을 위한 좋은 API를 설계할 때, 첫 번째 단계는 최소한의 사용 패턴, 온보딩, 그리고 상위 10가지 사용 사례를 스케치하는 것입니다. 이를 바탕으로 이를 구현하기 위해 이상적으로 작성하고 싶은 코드를 상상합니다. 그런 다음 직접 사용해 보고, 막히는 부분을 찾아 필요할 때 적절한 기본값(default)과 설정을 추가합니다. 나는 사람들이 단 50줄만으로도 기능적인 무언가를 가질 수기를 원합니다. 거기서부터 API는 더 많은 기능을 찾기 쉬울 만큼 접근하기 쉬워야 하며, 사용자가 자연스럽게 찾을 수 있는 곳에 있어야 합니다. 이상적으로는 20개의 필드 중 단 하나만 필요한 사람이 자신이 원하는 필드의 자동완성을 통해 나머지 19개의 필드를 알게 되는 정도면 충분합니다. 좋은 SDK(Software Development Kit)는 문서를 겉핥기식으로만 읽고서도 사용할 수 있을 만큼 자명해야 하며, 그마저도 필요하지 않을 정도여야 합니다.

훌륭한 사례들: 스트라이프(Stripe)와 트윌리오(Twilio)는 위의 가치를 구현한 훌륭한 예시입니다. 필자는 14살 때 이 둘을 아무런 문제 없이 구현했는데, 스트라이프의 세금 옵션이나 ACH가 무엇인지, 혹은 스트라이프가 하는 50가지 다른 일들에 대해 배울 필요가 없었습니다. 트윌리오의 스케줄링이나 봇 등에 대해서도 마찬가지였습니다. 나중에야 그것들에 대해 알게 되었습니다. 하지만 이 SDK들은 내가 실제로 무슨 일이 일어나고 있는지에 대해 많이 알지 못한 채로도 엄청난 진전을 만들어낼 수 있게 해주었습니다.

이것은 에이전트를 위해 설계해야 하는 방식과는 정반대입니다. AI 에이전트는 한 번에 문서 전체를 읽을 수 있습니다. 평균적인 Claude Code 프롬프트는 10k 토큰 이상을 사용하며, 첫 번째 프롬프트에서 에이전트는 API 전체와 모든 관련 문서를 읽을 수 있습니다. 또한 목표를 달성하기 위해 몇 초 만에 수천 줄의 코드를 생성할 수 있습니다. 이것은 모든 것을 바꿔놓았습니다.

에이전트를 위한 좋은 API 에이전트는 무엇보다 '명확성'이 필요합니다. 즉, 코드를 읽는 것만으로도 그것이 정확히 무슨 역할을 하는지 알려주는 API여야 합니다. AI 에이전트 시대에는 코드의 양이 훨씬 많아져서 디버깅이 훨씬 어려워지며, 이를 해결할 수 있는 유일한 방법은 코드가 수행할 작업에 대해 정확한 정의를 내리는 것뿐입니다.

그 의미는 다음과 같습니다: 기본값은 이제 나쁩니다. 에이전트는 문서를 읽고, 좋은 시작 값이 무엇인지 파악하여, 그것들을 제자리에 모두 채워 넣을 수 있다고 기대할 수 있습니다. 이제 명시적인 것은 비용이 들지 않으며, 예상되는 동작에 구체성을 부여하면 버그가 줄어듭니다. 위에서 언급한 예시에서 나는 이해하지 못했기 때문에 채우지 않았던 30개의 필드가 있었습니다. 에이전트는 모든 필드를 다 채워야 합니다. 이것은 덜 중요한 필드들 사이에 주석을 달아 더 중요한 필드들과 구분해서는 안 된다는 말이 아닙니다. 단지 방대한 양의 언뜻 보기에 덜 중요해 보이는 필드를 채우는 데 들어가는 비용은 사라졌지만, 코드가 실제로 어떤 일을 하는지 이해하는 데 드는 비용은 급격히 증가했다는 것을 의미합니다.

에러는 나쁘지 않습니다. 내가 사용해 본 훌륭한 API 중 상당수는 내 실수를 부드럽게 덮어주었습니다. 소문자만 허용하는 필드에 대문자를 입력해도 이를 소문자로 변환해 통합하거나, PostgreSQL의 불린(boolean) 타입이 true, yes, on, 1을 동일하게 받아들이는 것처럼 같은 기능에 대해 여러 키를 인정하는 식이었습니다. 하지만 이것은 에이전트 코드베이스에는 오히려 안 좋습니다. 이로 인해 다른 함수들이 같은 것에 대해 다른 값을 사용하게 되어, 나중에 코드를 리뷰하는 사람들에게 골칫거리가 생깁니다. 최신 프레임워크는 디버깅 중에 문서를 읽을 수 있다고 기대할 수 있으며, 에러 메시지를 통해 에이전트에게 문서를 확인하라고 지시하면 더욱 좋습니다. 절반만 맞는 식의 값 통합은 일어나지 않아야 하며, 에이전트가 원하는 대로 명시적으로 값을 처리하도록 내버려 두어야 합니다. 인간에게 온보딩 단계의 에러는 좋지 않은 것이므로 최소화해야 합니다. 하지만 에이전트에게는 에러가 무언가의 실제 의미를 명확히 할 수 있는 기회가 됩니다.

물론 이것이 모든 에러가 좋다는 것을 의미하지는 않습니다. 방향성이 없는 빈 내부 에러는 에이전트를 혼란(무한 루프)에 빠뜨리지만, 이는 나쁜 에러에 대한 반론일 뿐 에러 자체에 대한 반론은 아닙니다. 좋은 에러는 놀라운 도구입니다.

원문 보기
원문 보기 (영어)
Designing APIs for agents is different from designing them for humans. Most consumers of APIs today do so through agent-written code. This was not true two years ago, and it changes how we should think about designing them. I no longer believe in most systems built for humans. I'm skeptical of most packages, I'm anti-utility, and I'm pro extremely long names now — all opinions I've done complete 180s on in the past 24 months. Good APIs for humans When I design a good API for humans, my first step is sketching the minimal usage patterns, the onboarding, and the top ten use cases. From those, I imagine the code I'd ideally write to get there. Then I try using it, find the edges where I got stuck, and add good defaults and configuration where necessary. I want people to have something functional in fifty lines. From there, the API should be approachable enough that reaching for more functionality is obvious — that's where they'd look. Ideally, someone who needs only one of twenty fields should only become aware of the other nineteen through the autocomplete around the one they want. A good SDK should be self-explanatory enough that you can use it with only minimal skimming of the docs, if that. Some great examples: These embody the values above. I implemented both as a fourteen-year-old with no issues, and without having to learn about Stripe's tax options, what ACH is, or any of the fifty other things Stripe does — and without learning about Twilio's scheduling, bots, or anything else. Later on I did. But these SDKs let me make a ton of progress without knowing much about what was actually going on. This is the opposite of how you should design for agents AI agents can read our entire docs in one sitting. The average Claude Code prompt uses 10k+ tokens; on their first prompt, agents can read your entire API and every relevant document. They can also produce thousands of lines of code to reach their goals in seconds. This changes everything. Good APIs for agents Agents need clarity above everything else — APIs where reading the code tells you exactly what it does. There is a lot more code in the AI-agent era, which makes debugging much harder, and the only way to solve that is through precise definitions of what the code is expected to do. That means: Defaults are bad. Agents can be expected to read the documentation, register what good starting values are, and fill them all in, in place. Explicitness is cheap now, and bringing specificity to expected behavior reduces bugs. The examples above each had thirty fields I didn't fill in because I didn't comprehend them. An agent should fill in every single one. This isn't to say the less important fields shouldn't have a comment between them and the more important ones to separate them — just that the tax on filling out large amounts of seemingly unimportant fields has disappeared, while the tax of understanding what code does has gone way up. Errors are not bad. Many great APIs I've used have smoothed over my stupidity: accepting uppercase for lowercase-only fields and coalescing it, or accepting multiple keys for the same thing the way Postgres booleans accept true , yes , on , 1 . This is actively bad for agent codebases. It leads to different functions using different values for the same thing, which causes headaches for later reviewers. Modern harnesses can be expected to read the docs when debugging — bonus points if you tell them to in the error message. Half-correct coalescing should not happen; let the agent explicitly coalesce the values however it wants on its side. For humans, errors in onboarding are bad and you should minimize them. For agents, they are opportunities to clarify what something actually means. This doesn't mean all errors are good. Blank internal errors with no direction make agents spiral, but that's an argument against bad errors, not errors. A good error is an amazing tool: it means the AI had a misconception about your API and solved it. And it will have misconceptions. Even with everything in context, backwards compatibility breaks and confusion happens. Errors that lead to clarity solve this. In distribution, not in hallucination. When an API is unclear, agents tend to hallucinate and use it like similar APIs they've seen. For this reason I prefer specific field names to general ones. Take the field name . Some APIs use it for a display name, others for a full ID, others for a scoped ID. If you ask an agent to use an API with name in it across ten different use cases, it will use it in five different ways — and following the point above, only one can be right. Can name have spaces, slashes, dashes, underscores, emoji? This problem compounds as the codebase grows. Reviewers who read this code in the future will interpret name in those same five different ways again. Prefer explicitness: in place of name , I prefer displayName , slug , externalId , or anything you choose that won't carry the same assumptions. These are words an agent can truly understand — not get stumped by, and not misinterpret. Doc comments help cement the correct interpretation too. Facts, not feelings. The value of an API in the era of agents is that it provides a fact the agent or its human team cannot replicate internally. That can be the fact of a bill paid, a message sent, or a virtual machine provisioned (shameless plug for Freestyle VMs ). Utilities beyond that are largely irrelevant, and can be replaced with documentation and guides explaining how to get somewhere. In that vein, I'm fairly skeptical of most SDKs for APIs that do more than expose API norms in language-specific patterns — transforming API errors into strongly typed TypeScript errors, for example. Putting this into practice Freestyle builds the most powerful virtual machines in the sandbox space as measured by virtualization quality (we support everything others don't, like Docker-in-Docker, nested virtualization, and advanced networking), scale (we allow 8x larger memory footprints in our public tiers, and much more for enterprise), configuration (we support the full operating system, rootFS, and networking, including private VPCs and VPN connections), stability, and full memory snapshots that actually work ;) — all provisioned in 400ms. This puts us in a weird spot. We work with users solving fundamentally complex problems that are open-ended, hard to debug, and the most difficult in the industry — people come to us for what other sandboxes cannot do. To that end, we try our very best to not do much: just provide the facts I gave above, as consistently as possible. We used to try to hide as much of the complexity as we could. We built a declarative functional build system combined with SDK utilities that let us author packages that came with dependencies. The idea was: "If a user wants Bun, give them the Bun package and let them not worry about the internals, because we made Bun work well." But we didn't. It was never configurable enough, there were always more questions than answers, agents didn't get it and misused it in every possible way, and in the end the complexity of trying to use these abstract layers became the hardest part of onboarding to us. See below how beautiful the code snippet looks — and how little you get about what's going on in it. This was optimized around my former belief that humans needed to get something working fast and would dive into the details later. But we got rid of all of that months ago. We removed every complex SDK package and indirection in favor of a guide . Now when you want anything complex like that, you tell your agent to read the guide, it takes the code relevant to it, adapts it to your project's norms, customizes the behavior however it wants, and has a much cleaner onboarding experience combined with much clearer code at the end. In practice in other APIs and SDKs ���