Skip to content

Commit 35e8cfb

Browse files
committed
docs: add framework integration guides for LangChain, CrewAI, PydanticAI, LlamaIndex, Mastra, and Google ADK
1 parent bbeaa99 commit 35e8cfb

14 files changed

Lines changed: 1962 additions & 0 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ npx aimock convert mockllm ./config.yaml ./fixtures/
8888
docker run -d -p 4010:4010 -v ./fixtures:/fixtures ghcr.io/copilotkit/aimock -f /fixtures
8989
```
9090

91+
## Framework Guides
92+
93+
Test your AI agents with aimock — no API keys, no network calls: [LangChain](https://aimock.copilotkit.dev/integrate-langchain) · [CrewAI](https://aimock.copilotkit.dev/integrate-crewai) · [PydanticAI](https://aimock.copilotkit.dev/integrate-pydanticai) · [LlamaIndex](https://aimock.copilotkit.dev/integrate-llamaindex) · [Mastra](https://aimock.copilotkit.dev/integrate-mastra) · [Google ADK](https://aimock.copilotkit.dev/integrate-adk)
94+
9195
## Switching from other tools?
9296

9397
Step-by-step migration guides: [MSW](https://aimock.copilotkit.dev/migrate-from-msw) · [VidaiMock](https://aimock.copilotkit.dev/migrate-from-vidaimock) · [mock-llm](https://aimock.copilotkit.dev/migrate-from-mock-llm) · [Python mocks](https://aimock.copilotkit.dev/migrate-from-python-mocks) · [Mokksy](https://aimock.copilotkit.dev/migrate-from-mokksy)

docs/integrate-adk/index.html

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Google ADK — aimock</title>
7+
<link rel="icon" type="image/svg+xml" href="../favicon.svg" />
8+
<link rel="preconnect" href="https://fonts.googleapis.com" />
9+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10+
<link
11+
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400&family=Instrument+Sans:wght@400;500;600;700&display=swap"
12+
rel="stylesheet"
13+
/>
14+
<link rel="stylesheet" href="../style.css" />
15+
</head>
16+
<body>
17+
<nav class="top-nav">
18+
<div class="nav-inner">
19+
<div style="display: flex; align-items: center; gap: 1rem">
20+
<button
21+
class="sidebar-toggle"
22+
onclick="document.querySelector('.sidebar').classList.toggle('open')"
23+
aria-label="Toggle sidebar"
24+
>
25+
&#9776;
26+
</button>
27+
<a href="/" class="nav-brand"> <span class="prompt">$</span> aimock </a>
28+
</div>
29+
<ul class="nav-links">
30+
<li><a href="/">Home</a></li>
31+
<li><a href="/docs" style="color: var(--accent)">Docs</a></li>
32+
<li>
33+
<a href="https://github.com/CopilotKit/aimock" class="gh-link" target="_blank"
34+
><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
35+
<path
36+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
37+
/>
38+
</svg>
39+
GitHub</a
40+
>
41+
</li>
42+
</ul>
43+
</div>
44+
</nav>
45+
46+
<div class="docs-layout">
47+
<aside class="sidebar" id="sidebar"></aside>
48+
49+
<main class="docs-content">
50+
<h1>Google ADK</h1>
51+
<p class="lead">
52+
Test your Google ADK agents without Gemini API keys. aimock speaks the Gemini API format
53+
natively &mdash; <code>generateContent</code>, <code>streamGenerateContent</code>, and
54+
function calling.
55+
</p>
56+
57+
<h2>Quick Start</h2>
58+
<p>
59+
Point the Google Gen AI SDK at your aimock instance. ADK uses the Gen AI SDK under the
60+
hood, so this is all you need:
61+
</p>
62+
<div class="code-block">
63+
<div class="code-block-header">
64+
Configure the Gen AI client <span class="lang-tag">python</span>
65+
</div>
66+
<pre><code><span class="kw">from</span> google <span class="kw">import</span> genai
67+
68+
client = genai.<span class="fn">Client</span>(
69+
vertexai=<span class="kw">False</span>,
70+
api_key=<span class="str">"test"</span>,
71+
http_options={<span class="str">"api_version"</span>: <span class="str">"v1beta"</span>, <span class="str">"base_url"</span>: <span class="str">"http://localhost:4010"</span>},
72+
)</code></pre>
73+
</div>
74+
<p>
75+
Start aimock with a Gemini-format fixture, then run your ADK agent. Requests to
76+
<code>generateContent</code> and <code>streamGenerateContent</code> are handled
77+
automatically.
78+
</p>
79+
<div class="code-block">
80+
<div class="code-block-header">Start aimock <span class="lang-tag">shell</span></div>
81+
<pre><code>npx aimock --fixtures fixtures/examples/adk/gemini-agent.json</code></pre>
82+
</div>
83+
84+
<h2>Gemini API Format</h2>
85+
<p>
86+
aimock handles the Gemini native request and response format. ADK agents hit these
87+
endpoints:
88+
</p>
89+
<table class="endpoint-table">
90+
<thead>
91+
<tr>
92+
<th>Method</th>
93+
<th>Path</th>
94+
<th>Format</th>
95+
</tr>
96+
</thead>
97+
<tbody>
98+
<tr>
99+
<td>POST</td>
100+
<td><code>/v1beta/models/{model}:generateContent</code></td>
101+
<td>JSON</td>
102+
</tr>
103+
<tr>
104+
<td>POST</td>
105+
<td><code>/v1beta/models/{model}:streamGenerateContent</code></td>
106+
<td>JSON stream / SSE (with <code>?alt=sse</code>)</td>
107+
</tr>
108+
<tr>
109+
<td>WS</td>
110+
<td><code>/ws/google.ai.generativelanguage.*</code></td>
111+
<td>Gemini Live WebSocket</td>
112+
</tr>
113+
</tbody>
114+
</table>
115+
<p>
116+
Gemini uses <code>contents</code> with <code>parts</code> rather than OpenAI's
117+
<code>messages</code> array. aimock translates Gemini requests to the unified fixture
118+
format internally, so the same <code>match.userMessage</code> works regardless of which
119+
provider endpoint the request arrives on.
120+
</p>
121+
122+
<h2>Function Calling</h2>
123+
<p>
124+
ADK agents rely heavily on Gemini function calling. The Gemini format uses
125+
<code>functionCall</code> and <code>functionResponse</code> parts instead of the
126+
OpenAI-style <code>tool_calls</code> array. aimock generates the correct Gemini response
127+
shape from the same fixture format:
128+
</p>
129+
<div class="code-block">
130+
<div class="code-block-header">
131+
Function calling fixture <span class="lang-tag">json</span>
132+
</div>
133+
<pre><code>{
134+
<span class="prop">"fixtures"</span>: [
135+
{
136+
<span class="prop">"match"</span>: { <span class="prop">"userMessage"</span>: <span class="str">"weather"</span> },
137+
<span class="prop">"response"</span>: {
138+
<span class="prop">"toolCalls"</span>: [
139+
{
140+
<span class="prop">"name"</span>: <span class="str">"get_weather"</span>,
141+
<span class="prop">"arguments"</span>: <span class="str">"{\"city\":\"San Francisco\",\"unit\":\"fahrenheit\"}"</span>
142+
}
143+
]
144+
}
145+
}
146+
]
147+
}</code></pre>
148+
</div>
149+
<p>
150+
When a Gemini endpoint receives this fixture, aimock returns it as a
151+
<code>functionCall</code> part:
152+
</p>
153+
<div class="code-block">
154+
<div class="code-block-header">
155+
Gemini response shape <span class="lang-tag">json</span>
156+
</div>
157+
<pre><code>{
158+
<span class="prop">"candidates"</span>: [{
159+
<span class="prop">"content"</span>: {
160+
<span class="prop">"role"</span>: <span class="str">"model"</span>,
161+
<span class="prop">"parts"</span>: [{
162+
<span class="prop">"functionCall"</span>: {
163+
<span class="prop">"id"</span>: <span class="str">"call_abc123"</span>,
164+
<span class="prop">"name"</span>: <span class="str">"get_weather"</span>,
165+
<span class="prop">"args"</span>: { <span class="prop">"city"</span>: <span class="str">"San Francisco"</span>, <span class="prop">"unit"</span>: <span class="str">"fahrenheit"</span> }
166+
}
167+
}]
168+
}
169+
}]
170+
}</code></pre>
171+
</div>
172+
173+
<h2>With aimock-pytest</h2>
174+
<p>
175+
The <code>aimock-pytest</code> plugin provides a <code>aimock</code> fixture that starts
176+
and stops the server automatically:
177+
</p>
178+
<div class="code-block">
179+
<div class="code-block-header">conftest.py <span class="lang-tag">python</span></div>
180+
<pre><code><span class="kw">import</span> pytest
181+
182+
<span class="cm"># The aimock fixture is provided by aimock-pytest</span>
183+
<span class="cm"># pip install aimock-pytest</span></code></pre>
184+
</div>
185+
<div class="code-block">
186+
<div class="code-block-header">
187+
test_adk_agent.py <span class="lang-tag">python</span>
188+
</div>
189+
<pre><code><span class="kw">from</span> google <span class="kw">import</span> genai
190+
191+
<span class="kw">def</span> <span class="fn">test_agent_weather_tool</span>(aimock):
192+
<span class="cm">"""Test that ADK agent calls get_weather tool."""</span>
193+
aimock.<span class="fn">load_fixtures</span>(<span class="str">"fixtures/examples/adk/gemini-agent.json"</span>)
194+
195+
client = genai.<span class="fn">Client</span>(
196+
vertexai=<span class="kw">False</span>,
197+
api_key=<span class="str">"test"</span>,
198+
http_options={<span class="str">"api_version"</span>: <span class="str">"v1beta"</span>, <span class="str">"base_url"</span>: aimock.url},
199+
)
200+
201+
response = client.models.<span class="fn">generate_content</span>(
202+
model=<span class="str">"gemini-2.0-flash"</span>,
203+
contents=<span class="str">"what is the weather in San Francisco?"</span>,
204+
)
205+
206+
<span class="cm"># Verify the tool call was returned</span>
207+
part = response.candidates[<span class="num">0</span>].content.parts[<span class="num">0</span>]
208+
<span class="kw">assert</span> part.function_call.name == <span class="str">"get_weather"</span></code></pre>
209+
</div>
210+
211+
<h2>CI with GitHub Action</h2>
212+
<p>
213+
Use the <a href="/github-action">aimock GitHub Action</a> to run aimock as a service in
214+
CI:
215+
</p>
216+
<div class="code-block">
217+
<div class="code-block-header">
218+
.github/workflows/test.yml <span class="lang-tag">yaml</span>
219+
</div>
220+
<pre><code><span class="prop">steps</span>:
221+
- <span class="prop">uses</span>: actions/checkout@v4
222+
- <span class="prop">name</span>: <span class="str">Start aimock</span>
223+
<span class="prop">uses</span>: CopilotKit/aimock@v1
224+
<span class="prop">with</span>:
225+
<span class="prop">fixtures</span>: fixtures/examples/adk/gemini-agent.json
226+
227+
- <span class="prop">name</span>: <span class="str">Run ADK tests</span>
228+
<span class="prop">run</span>: pytest tests/</code></pre>
229+
</div>
230+
<p>
231+
No real Gemini API keys needed in CI &mdash; aimock does not validate them. Note that ADK
232+
/ the Google Gen AI SDK does not support a <code>base_url</code> environment variable
233+
override, so you must configure the base URL programmatically in your test code using
234+
<code>http_options</code> (see the pytest example above).
235+
</p>
236+
237+
<h2>Arbitrary Path Prefixes</h2>
238+
<p>
239+
If your ADK configuration or a proxy layer adds a non-standard base URL prefix (e.g.
240+
<code>/my-app/v1beta/models/...</code>), aimock normalizes it automatically. The
241+
<code>normalizeCompatPath</code> feature strips arbitrary prefixes and rewrites paths
242+
ending in known suffixes to their canonical form.
243+
</p>
244+
<p>
245+
This means your ADK agent can use any base URL structure and aimock will still route the
246+
request correctly to the Gemini handler.
247+
</p>
248+
<div class="code-block">
249+
<div class="code-block-header">
250+
Non-standard prefix example <span class="lang-tag">python</span>
251+
</div>
252+
<pre><code><span class="cm"># Even with a custom prefix, aimock routes correctly</span>
253+
client = genai.<span class="fn">Client</span>(
254+
vertexai=<span class="kw">False</span>,
255+
api_key=<span class="str">"test"</span>,
256+
http_options={
257+
<span class="str">"api_version"</span>: <span class="str">"v1beta"</span>,
258+
<span class="str">"base_url"</span>: <span class="str">"http://localhost:4010/my-proxy"</span>,
259+
},
260+
)</code></pre>
261+
</div>
262+
</main>
263+
<aside class="page-toc" id="page-toc"></aside>
264+
</div>
265+
<footer class="docs-footer">
266+
<div class="footer-inner">
267+
<div class="footer-left"><span>$</span> aimock &middot; MIT License</div>
268+
<ul class="footer-links">
269+
<li><a href="https://github.com/CopilotKit/aimock" target="_blank">GitHub</a></li>
270+
<li>
271+
<a href="https://www.npmjs.com/package/@copilotkit/aimock" target="_blank">npm</a>
272+
</li>
273+
</ul>
274+
</div>
275+
</footer>
276+
<script src="../sidebar.js"></script>
277+
<script src="../cli-tabs.js"></script>
278+
</body>
279+
</html>

0 commit comments

Comments
 (0)