Strands vs ADK in Practice: Building an AI Learning System from Scratch — Which Comes Out on Top?

A developer built the same AI course system with Strands and ADK, revealing real framework differences and pitfalls.
Based on a developer's real retrospective building an AI course-generation system with Strands and Google ADK, this article compares the frameworks on doc scraping, typed output, feedback loops, and cost control. It stresses that mock tests passing doesn't mean the system works — real models must be used. ADK's plugin mechanism and function nodes are more flexible, while Strands' execution caps and streaming are more intuitive. Course quality depends on reviewer strictness, and cost control requires cumulative metering across calls. The author picks Strands but recommends having a second model review the first model's output.
Strands vs ADK in Practice: Building an AI Learning System from Scratch — Which Comes Out on Top?
When AI framework comparisons shift from spec sheets to real projects, the gaps finally show. One developer built an AI course-generation system with both Strands and Google ADK — from doc scraping to quiz design, from feedback loops to cost control — and the two frameworks behaved in completely different ways. Based on that detailed retrospective, this article breaks down the key differences and hard-won lessons.

Why AI course generation needs a rethink
In Part 1, the author declared "we can build this now." In Part 2, he actually did it: implementing the same learning system with two frameworks and feeding them identical requests to compare the quality of the courses they produced.
The first version, generated by Claude Opus, included 235 tests — all passing. But the author discovered those tests never talked to a real model. When he hooked up the real model, the first call failed; even after it eventually generated a Terraform course, quiz answers appeared directly below the questions, and every exercise shipped with a completed solution file. The whole project was scrapped and rebuilt.
The story exposes a common trap: passing tests does not mean the system works. Especially in AI application development, the behavioral gap between a mock model and the real one can render every test meaningless.
What a learning system should be able to do
The author reworked the requirements list, which also became the benchmark for evaluating both frameworks:
- After the user states a learning goal, the system asks a few questions to tailor the course;
- Content covers real-world work scenarios, such as module version pinning;
- Information is in sync with the official docs as of the build date;
- Learning is validated through hands-on exercises and tests;
- Try first, then see the answer;
- Build costs are controllable and transparent.
These requirements drove every subsequent technical decision.
The experience: one command to start course generation
After installation, the user just runs:
learn "I want to learn TypeScript so I can build a small web app"
The system asks about background and goals, then automatically scrapes the official docs, plans the curriculum, and writes the course content. The author showed the output of a real run: 126 facts checked, 5 units and 12 lessons planned, final cost about $2.94.
During learning, the user can run learn check to execute real tests, learn hint to get hints one at a time, and learn quiz to answer questions before seeing explanations. This design enforces the "try before you see the answer" principle.
Architecture: one Brain interface, two implementations
The whole system is built around a Brain protocol:
class Brain(Protocol):
def ask(self, name: str, instruction: str, prompt: str, schema: type[T], research: bool = False) -> T:
"""One agent call, returning `schema`. With research=True the agent can search and read."""
Strands uses Claude Sonnet 4.6 (via Amazon Bedrock); ADK uses Gemini 3.8 Flash. Each framework implements ask differently and runs its own graph structure. This design keeps the comparison fair.
How the researcher gets the latest docs
The two frameworks differ markedly in tool integration. Strands doesn't ship a search tool of its own and needs an MCP server; ADK has built-in google_search but only for Gemini models.
The author tested with the same AWS documentation MCP server. Strands connects via MCPClient and passes tools directly; ADK integrates through McpToolset. For reading pages, Strands' web_fetch supports a markdown mode that returns the original text, making verbatim fact-checking easy; ADK's load_web_page has issues with redirects and short-line filtering, causing large numbers of code examples to be lost.
A key finding: the model can give wrong answers. Asked about the S3 object size limit, Claude said 5TB and Gemini said 50TB, while the official AWS docs say 50TB. Claude searched once and cited a result that mentioned both numbers; Gemini kept digging into the FAQ page. This pushed the author to require that every fact carry a verbatim citation.
MCP (Model Context Protocol) is an open protocol proposed by Anthropic in late 2024 to standardize how AI models connect to external tools and data sources. It uses a client-server architecture: the model calls tools exposed by an MCP server (search, database queries, file reading, etc.) through an MCP client. In this article, the developer uses an AWS documentation MCP server so the AI can fetch the latest official docs — Strands integrates it directly via MCPClient, while ADK wraps it with McpToolset. The value of MCP is decoupling: a tool provider implements an MCP server once, and any MCP-compatible framework can reuse it, avoiding the need to build integration code repeatedly for each framework.
Typed output: Strands returns objects directly, ADK requires manual conversion
Both frameworks support Pydantic models, but the usage differs. Strands takes structured_output_model= at call time and exposes the result via result.structured_output — directly a model instance. ADK sets output_schema= on the Agent, and the result lands in session state as a dictionary that must be manually converted with model_validate.
ADK also introduces a hidden problem: when an Agent has both output_schema and built-in tools, ADK automatically adds a function tool named set_model_response, which conflicts with Gemini API built-in tools — you must set include_server_side_tool_invocations=True to fix it. This error cannot be caught by mock-model tests.
Pydantic is a widely used data validation library in the Python ecosystem: you define data models with type annotations, and it performs runtime type checking and conversion automatically. In AI agent development, Pydantic models are often used to constrain the output format of large language models — the developer defines a class inheriting from BaseModel (e.g., CoursePlan), the framework converts it to a JSON Schema, requires the model to generate content in that structure, and then parses it back into model instances. This is more reliable than free-text output and easier to process programmatically. In this article, both frameworks support Pydantic models as output schemas, but Strands returns model instances directly while ADK returns dictionaries that need manual model_validate conversion — a reflection of their different designs for the typed-output pipeline.
Feedback loops: Strands has an execution cap, ADK needs its own control
In Strands, graph nodes must be Agents or subclasses of MultiAgentBase; a plain function throws ValueError at runtime. The author wrapped each stage as a MultiAgentBase subclass and used set_max_node_executions() to cap the number of node executions — once exceeded, the graph state becomes FAILED.
ADK nodes can be arbitrary functions, which is more flexible, but there is no built-in loop limit; the routing function must decide when to stop.
Both implementations let a review node send problems back upstream, but the author found a real issue: when review asked for more research, Strands discarded the 306 facts it had already checked and started over, driving a single run's cost up to $11.81. After the fix, the research phase keeps verified content and only fills in what's missing.
In graph-based agent frameworks, a cap on node executions is a key safety mechanism against infinite loops. Strands' graph engine requires nodes to be Agents or subclasses of MultiAgentBase, with a hard cap set via set_max_node_executions() — once exceeded, the graph state becomes FAILED, effectively preventing runaway retries and costs caused by logic errors or model anomalies. ADK is more flexible: nodes can be arbitrary functions, but the framework provides no built-in loop limit, so developers must implement termination conditions themselves in routing functions. This design difference reflects two philosophies: Strands favors safety under constraints, ADK favors freedom with responsibility. In real projects, the lack of a hard cap can lead to unexpectedly high API bills, so extra care is needed.
Cost control: the plugin mechanism gives ADK the edge
Course generation involves hundreds of model calls, so cost control is critical. Strands uses add_hook to attach a hook to each Agent, checking cumulative spend before model calls; ADK achieves similar functionality with before_model_callback and after_model_callback, and supports a plugin mechanism — register once and it applies to all Agents.
Both frameworks have exception-propagation pitfalls: Strands wraps exceptions after tool execution into EventLoopException; ADK emits an error event first and then throws at the end of the stream.
Real cost data: building the Terraform course cost $18.36 with Strands and only $3.35 with ADK (excluding upfront research and planning). But the author also fixed several metering bugs, such as using id(agent) as a key causing miscounts, and budgets resetting after a process restart.
To handle cost caps, the system now automatically switches to a cheaper model when spend reaches half the cap, and clearly tells the user.
In agent frameworks, hooks and callbacks are mechanisms for intercepting and extending the model call lifecycle. Strands registers hooks per Agent via add_hook, which can check cumulative spend before model calls and decide whether to continue; ADK provides before_model_callback and after_model_callback plus a plugin mechanism that applies globally to all Agents with a single registration. This plugin design reduces duplicated code and makes it easier to maintain a unified cost-control policy. However, both require attention to exception propagation: Strands wraps exceptions after tool execution into EventLoopException, while ADK emits an error event first and throws at the end of the stream — both affect the accuracy of error handling and metering logic.
Course quality: a tug of war between fact count and review strictness
The final comparison: Strands (Claude) checked 546 facts and generated 23 lessons, but only 12 exercises passed all checks; ADK (Gemini) checked 162 facts and generated 12 lessons, with every exercise passing. On cost, ADK was clearly lower.
However, after doing the exercises himself, the author found more problems. The ADK course initially had 5 exercises that failed its own checks, rooted in tests using command = plan instead of command = apply. After the fix, some TODOs could still pass tests without being completed, so per-TODO verification was added.
Quiz answer distribution also exposed model preferences: Gemini put the correct answer in the first position 83% of the time, while Claude preferred the second position (58%). Option randomization has now been added.
On review: the Gemini reviewer passed all 12 ADK lessons, while the Claude reviewer passed none of the Strands lessons. After swapping reviewers, Claude found 29 issues in the ADK course, most of them real. Reviewer strictness directly affects the surface quality of a course.
Missing real-world work scenarios
The author specifically notes that both courses omitted "module version pinning," an everyday work practice. Although the docs mention it, the researcher built the plan around document structure and never made it a standalone objective. The fix: during research, explicitly list "what people actually do at work" and map each item to a course objective.
Another safety concern: the last 6 lessons of the Strands course were configured to use a real AWS account, and two of them asked users to run terraform apply, potentially creating real resources unintentionally. Although learn check uses mock providers and never touches AWS, the author updated the README with a warning.
The final choice: Strands vs ADK
The author's personal choice is Strands, mainly because it's simpler to get started, the graph execution has a hard cap, and streaming output is more intuitive. But ADK is better in these respects: it only needs a Gemini API key to run, adk web provides in-browser chat and call tracing, any function can be a workflow node, and google_search got the latest versions right 8 out of 8 times.
The final recommendation: whichever framework you choose, have a second model review the output of the first. Both frameworks can run the same stages and typed answers; course quality depends more on model capability and the robustness of the checking mechanisms.
All course code is open-sourced on GitHub; each lesson lists known issues at the top, and feedback via Issues is welcome.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.