Skip to content

Commit f1d0cf3

Browse files
v0.3 deliverables: 5 integration guides + multi-agent bench (ADR 0006 §2.2 + §2.3)
Implements ADR 0006's two highest-ROI v0.3 deliverables ahead of alignment training. All work is purely additive (new files only, zero diff against existing code). ADR 0006 §2.2: docs/integrations/ (5 guides + index) ---------------------------------------------------- README.md Index + matrix + common server config + global compatibility notes (122 lines) langchain.md ChatOpenAI(base_url=...) + multi-agent asyncio.gather example + tool calling (122) crewai.md CrewAI LLM(base_url=...) + 3-agent crew with parallel-task DAG (127) autogen.md AutoGen v0.4+ OpenAIChatCompletionClient + model_info config + RoundRobinGroupChat (142) cursor-bridge.md Cursor IDE 'Override OpenAI Base URL' setup + multi-window concurrency demo (99) openwebui.md Open WebUI Docker setup + LM Studio custom endpoint + multi-tab demo (107) Each guide has the same structure per ADR 0006 §2.2: 1. Required Kakeya server config 2. Framework client config (5-10 lines) 3. Worked example demonstrating multi-agent concurrent execution (the discriminator vs mlx_lm.server) 4. Tool calling notes 5. Caveats: temperature ignored, Qwen3-only, sink+window context, etc. ADR 0006 §2.3: scripts/bench_agentic/bench_multi_agent.py --------------------------------------------------------- CLI bench that runs N concurrent simulated agents (each through M turns of multi-turn dialogue) against any OpenAI-compatible endpoint. Optionally repeats the workload against a parallel mlx_lm.server for direct headline comparison. Discriminator metric: wall-clock time for N concurrent multi-turn agent sessions: Kakeya (--max-concurrent N): t_wall ≈ max(t_agent_i) + admission mlx_lm.server (single-tenant): t_wall ≈ sum(t_agent_i) Reports per-agent timings, p50/p95 turn time, throughput, and the headline 'wall-time speedup' + 'throughput speedup' ratios. Persists JSON to results/platform-tests/ for v0.3 release notes. --dry-run flag exercises argparse + structure without HTTP traffic for CI / smoke validation. scripts/bench_agentic/__init__.py Package marker + scope doc scripts/bench_agentic/bench_multi_agent.py 470 lines: - Workload definition (8 agent prompts + 5 continuation prompts) - run_agent_session(): drives one agent through N turns - run_workload(): asyncio.gather across N concurrent agents - _aggregate(): wall-time, p50, p95, throughput, concurrency utilization - render_summary(): tabular summary including headline speedup - argparse with --kakeya-url + --mlx-lm-url for direct comparison - JSON report + structured stdout Verification on Linux VM ------------------------ python3 scripts/bench_agentic/bench_multi_agent.py --dry-run \ --n-agents 5 --n-turns 3 \ --mlx-lm-url http://localhost:8001 --mlx-lm-model Qwen/Qwen3-1.7B -> argparse OK; would run n_agents=5 n_turns=3, would compare with mlx_lm.server python3 scripts/bench_agentic/bench_multi_agent.py --help -> full --help renders cleanly ast.parse(...) syntax OK on all 8 new files Real-machine end-to-end run requires a running Kakeya server (and optionally a parallel mlx_lm.server) — that is the user/Mac side verification step. Output JSON shape is intentionally similar to existing bench_mlx_*.py reports so downstream tooling reuses. Pre-existing test failures (NOT introduced by this PR) ------------------------------------------------------ pytest tests/inference_engine/server/test_app_streaming.py -> 5 failed on main itself (with my changes stashed): test_stream_concatenated_content_matches_engine_decode test_stream_finish_reason_length_on_max_tokens test_stream_returns_done_sentinel_at_end test_stream_each_chunk_has_required_openai_fields test_stream_completion_id_consistent_across_chunks -> Error: 'asyncio.locks.Event ... is bound to a different event loop' -> Likely caused by dep version drift (httpx 0.28, sse-starlette 2.4) interacting with shared async fixtures. -> This PR is purely additive (no diff against any existing file) and cannot have caused these. Deserves a separate fix PR. After this PR ------------- v0.3.0 release notes can lead with the agentic-infrastructure framing (ADR 0006 §2.1) backed by: - 5 integration guides (this PR) - bench_multi_agent.py speedup numbers (run on Mac M4 — user's task) - additional bench scripts in v0.3 sequence (long_session, tool_call_reliability, cancellation, persistent_memory) Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent 9d2c8d6 commit f1d0cf3

8 files changed

Lines changed: 1185 additions & 0 deletions

File tree

docs/integrations/README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Kakeya Integrations
2+
3+
Drop-in guides for the most common ways to consume the Kakeya engine
4+
from agent frameworks and chat clients. Every integration speaks the
5+
OpenAI-compatible API exposed by `scripts/serve.py`, so plugging
6+
Kakeya into an existing application is typically a 1–3 line change to
7+
the client config.
8+
9+
The discriminator between Kakeya and other local-OpenAI-compat
10+
servers (`mlx_lm.server`, `llama.cpp` server, Ollama, LM Studio) is
11+
**multi-agent concurrent execution**: Kakeya's scheduler admits
12+
multiple sessions in parallel under `--max-concurrent N`, with
13+
configurable admission policies and per-session lifecycle. Each
14+
integration guide below shows how that capability surfaces in the
15+
respective framework.
16+
17+
## Matrix
18+
19+
| Framework / Client | OpenAI base URL config | Multi-agent supported | Tool calls | Streaming | Guide |
20+
| --- | --- | --- | --- | --- | --- |
21+
| **LangChain** | `ChatOpenAI(base_url=...)` | yes (asyncio.gather) | yes | yes | [langchain.md](langchain.md) |
22+
| **CrewAI** | `LLM(base_url=...)` | yes (Crew with N agents) | yes | yes | [crewai.md](crewai.md) |
23+
| **Microsoft AutoGen** | `OpenAIChatCompletionClient(base_url=...)` | yes (GroupChat) | yes | yes | [autogen.md](autogen.md) |
24+
| **Cursor** | Settings → Override OpenAI Base URL | yes (multiple windows) | yes | yes | [cursor-bridge.md](cursor-bridge.md) |
25+
| **Open WebUI / LM Studio** | OpenAI URL field | one chat at a time | yes | yes | [openwebui.md](openwebui.md) |
26+
27+
## Common server-side setup
28+
29+
All integrations assume a Kakeya server is running. The minimal
30+
multi-agent-ready invocation:
31+
32+
```bash
33+
PYTHONPATH=. python3 scripts/serve.py \
34+
--backend mlx \
35+
--verifier-id Qwen/Qwen3-1.7B \
36+
--max-concurrent 4 \
37+
--admission-policy queue \
38+
--queue-max-wait-s 30 \
39+
--host 127.0.0.1 --port 8000
40+
```
41+
42+
The `--max-concurrent 4` is the load-bearing flag: it tells the
43+
scheduler to admit up to 4 simultaneous sessions. Combined with
44+
`--admission-policy queue`, additional clients block in a fair FIFO
45+
until a slab frees up rather than failing with HTTP 429.
46+
47+
For production deployments add an API key:
48+
49+
```bash
50+
PYTHONPATH=. python3 scripts/serve.py ... \
51+
--api-key sk-prod-$(openssl rand -hex 16)
52+
```
53+
54+
Every integration guide below uses `sk-test-1` as the API key
55+
placeholder; replace with your real key.
56+
57+
## Compatibility notes that apply to every framework
58+
59+
These hold regardless of which framework you use; documenting once
60+
here saves duplicating in every guide:
61+
62+
- **`temperature` / `top_p` / `stop` accepted but ignored.** Kakeya
63+
decoder is greedy temperature-0 by design (ADR 0001 §2.2). Setting
64+
these does not error, but does not change output. If you need
65+
temperature > 0, this engine is the wrong choice today.
66+
- **`stream: true` works.** SSE format follows the OpenAI spec
67+
including the literal `data: [DONE]` terminator. OpenAI client
68+
libraries parse it without modification.
69+
- **`tools` / `function_call` accepted at the schema layer.** The
70+
underlying verifier (Qwen3) decides whether to emit a tool call.
71+
No native grammar-constrained sampling is enforced; reliability of
72+
JSON output depends on the verifier's training.
73+
- **Pool-full → HTTP 429.** Under default `--admission-policy reject`
74+
a busy server returns `429 Too Many Requests` with an OpenAI-format
75+
error envelope. Most frameworks retry on 429 by default. Switch to
76+
`queue` admission policy if you prefer the client to wait silently.
77+
- **`/healthz` always public, no auth required.** Useful for
78+
liveness probes and load balancer health checks.
79+
- **`/metrics` always public, no auth required.** Prometheus
80+
exposition format, ready to scrape.
81+
82+
## Why these five frameworks
83+
84+
The five chosen for v0.3.0 cover the practical surface of "running a
85+
local agent or chat assistant in 2026":
86+
87+
- **LangChain**: dominant agent / RAG / chain orchestration library;
88+
reaches the largest user base via community ecosystem.
89+
- **CrewAI**: most prominent multi-agent collaboration framework;
90+
showcases multi-agent concurrency directly.
91+
- **AutoGen**: Microsoft's research-focused multi-agent framework;
92+
often the first stop for people building research agents.
93+
- **Cursor**: dominant AI-assisted IDE; demonstrates Kakeya as a
94+
local backend for IDE workflows.
95+
- **Open WebUI / LM Studio**: GUI clients many users prefer over
96+
CLI; demonstrates Kakeya works for non-developer users too.
97+
98+
Adding more integrations (Ollama proxy bridge, vercel/ai-sdk,
99+
Continue.dev, etc.) is welcome but not v0.3.0 critical-path.

docs/integrations/autogen.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Kakeya + Microsoft AutoGen
2+
3+
Microsoft's AutoGen is a research-focused multi-agent framework
4+
where agents communicate through a `GroupChat`. It pairs naturally
5+
with Kakeya's scheduler — multiple `AssistantAgent` instances each
6+
take their turn against one shared backend.
7+
8+
## Server-side
9+
10+
```bash
11+
PYTHONPATH=. python3 scripts/serve.py \
12+
--backend mlx \
13+
--max-concurrent 4 \
14+
--admission-policy queue \
15+
--api-key sk-test-1
16+
```
17+
18+
## Client-side
19+
20+
AutoGen v0.4+ uses the `autogen-agentchat` + `autogen-ext` packages.
21+
22+
```python
23+
# pip install autogen-agentchat autogen-ext[openai]
24+
from autogen_ext.models.openai import OpenAIChatCompletionClient
25+
from autogen_agentchat.agents import AssistantAgent
26+
27+
# Construct the OpenAI-compat client pointing at Kakeya
28+
client = OpenAIChatCompletionClient(
29+
model="kakeya-v1",
30+
base_url="http://127.0.0.1:8000/v1",
31+
api_key="sk-test-1",
32+
# AutoGen requires model_info to be set when using a custom
33+
# base_url because it does not know our model's capabilities.
34+
model_info={
35+
"function_calling": True,
36+
"json_output": True,
37+
"vision": False,
38+
"family": "qwen3",
39+
},
40+
)
41+
42+
assistant = AssistantAgent(
43+
name="assistant",
44+
model_client=client,
45+
system_message="You are a thoughtful helper.",
46+
)
47+
```
48+
49+
Single-turn smoke:
50+
51+
```python
52+
import asyncio
53+
from autogen_agentchat.messages import TextMessage
54+
from autogen_core import CancellationToken
55+
56+
async def main():
57+
response = await assistant.on_messages(
58+
[TextMessage(content="What is speculative decoding?", source="user")],
59+
cancellation_token=CancellationToken(),
60+
)
61+
print(response.chat_message.content)
62+
63+
asyncio.run(main())
64+
```
65+
66+
## Multi-agent group chat (the discriminator vs `mlx_lm.server`)
67+
68+
A planner + coder + reviewer trio collaborating on a small task.
69+
GroupChat dispatches the next-speaker decision; with three
70+
`AssistantAgent` objects backing onto the same Kakeya server, the
71+
scheduler handles their concurrent admission.
72+
73+
```python
74+
import asyncio
75+
from autogen_agentchat.agents import AssistantAgent
76+
from autogen_agentchat.teams import RoundRobinGroupChat
77+
from autogen_agentchat.conditions import MaxMessageTermination
78+
from autogen_ext.models.openai import OpenAIChatCompletionClient
79+
80+
client = OpenAIChatCompletionClient(
81+
model="kakeya-v1",
82+
base_url="http://127.0.0.1:8000/v1",
83+
api_key="sk-test-1",
84+
model_info={"function_calling": True, "json_output": True,
85+
"vision": False, "family": "qwen3"},
86+
)
87+
88+
planner = AssistantAgent(
89+
"planner", model_client=client,
90+
system_message="Decompose the user task into 2-3 concrete steps.",
91+
)
92+
coder = AssistantAgent(
93+
"coder", model_client=client,
94+
system_message="Write Python implementing the planned steps.",
95+
)
96+
reviewer = AssistantAgent(
97+
"reviewer", model_client=client,
98+
system_message="Critique the code; suggest one concrete improvement.",
99+
)
100+
101+
team = RoundRobinGroupChat(
102+
[planner, coder, reviewer],
103+
termination_condition=MaxMessageTermination(6),
104+
)
105+
106+
async def main():
107+
async for msg in team.run_stream(
108+
task="Write a function that computes Fibonacci numbers."
109+
):
110+
print(f"[{msg.source}] {msg.content[:200]}")
111+
112+
asyncio.run(main())
113+
```
114+
115+
In a `RoundRobinGroupChat` only one agent speaks at a time, so the
116+
multi-tenancy advantage shows up when you run **multiple
117+
GroupChats in parallel** (e.g., to A/B-test different prompts).
118+
119+
For genuine concurrent agent workloads, run independent
120+
`run_stream` invocations in parallel:
121+
122+
```python
123+
async def main():
124+
tasks = [team.run_stream(task=f"Topic {i}") for i in range(3)]
125+
# AutoGen's run_stream returns an async iterator; wrap each in a
126+
# consumer task and gather the results.
127+
consumers = [asyncio.create_task(_consume(t)) for t in tasks]
128+
await asyncio.gather(*consumers)
129+
```
130+
131+
## Caveats
132+
133+
- AutoGen v0.4+ requires `model_info` when using non-default
134+
`base_url`; the snippet above shows the minimal four fields.
135+
- `temperature` and other sampling params are accepted but ignored
136+
by Kakeya (greedy by design).
137+
- AutoGen's `JSONOutputMode` works because Kakeya passes through
138+
the `response_format` field; reliability depends on the
139+
underlying verifier.
140+
- For long-running multi-agent loops (`MaxMessageTermination(50)`),
141+
Kakeya's sink+window KV keeps memory bounded — this is exactly
142+
the scenario the architecture was designed for.

docs/integrations/crewai.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Kakeya + CrewAI
2+
3+
CrewAI orchestrates teams of agents that collaborate on complex
4+
tasks. Each agent has a role, a goal, and access to tools; the
5+
crew runs them sequentially or in parallel. Kakeya is a natural
6+
backend because the multi-agent execution model lines up directly
7+
with our scheduler's admission control.
8+
9+
## Server-side
10+
11+
```bash
12+
PYTHONPATH=. python3 scripts/serve.py \
13+
--backend mlx \
14+
--max-concurrent 5 \
15+
--admission-policy queue \
16+
--queue-max-wait-s 60 \
17+
--api-key sk-test-1
18+
```
19+
20+
`--max-concurrent 5` covers a typical 3–5-agent crew with one or two
21+
slabs to spare.
22+
23+
## Client-side
24+
25+
```python
26+
# pip install crewai
27+
from crewai import Agent, Task, Crew, LLM
28+
29+
llm = LLM(
30+
model="openai/kakeya-v1", # crewai expects the openai/ prefix
31+
base_url="http://127.0.0.1:8000/v1",
32+
api_key="sk-test-1",
33+
timeout=120,
34+
)
35+
36+
# Single-agent sanity check
37+
researcher = Agent(
38+
role="Researcher",
39+
goal="Surface 3 key facts about a given topic.",
40+
backstory="You are skeptical and source-driven.",
41+
llm=llm,
42+
verbose=True,
43+
)
44+
task = Task(
45+
description="Research transformer attention.",
46+
expected_output="Three concise bullets.",
47+
agent=researcher,
48+
)
49+
crew = Crew(agents=[researcher], tasks=[task])
50+
print(crew.kickoff())
51+
```
52+
53+
## Multi-agent crew (the discriminator vs `mlx_lm.server`)
54+
55+
Three agents collaborating on a code-review task. Each has a
56+
distinct role; CrewAI dispatches them in parallel where the
57+
dependency graph allows.
58+
59+
```python
60+
from crewai import Agent, Task, Crew, Process, LLM
61+
62+
llm = LLM(
63+
model="openai/kakeya-v1",
64+
base_url="http://127.0.0.1:8000/v1",
65+
api_key="sk-test-1",
66+
)
67+
68+
# Three specialized agents
69+
analyzer = Agent(role="Static Analyzer",
70+
goal="Identify bugs and code smells.",
71+
backstory="You think like a Rust borrow checker.",
72+
llm=llm)
73+
tester = Agent(role="Test Author",
74+
goal="Write unit tests covering edge cases.",
75+
backstory="You hate shipping untested code.",
76+
llm=llm)
77+
reviewer = Agent(role="Reviewer",
78+
goal="Synthesize feedback from analyzer and tester.",
79+
backstory="You write clear PR comments.",
80+
llm=llm)
81+
82+
snippet = "def divide(a, b): return a / b"
83+
84+
# Two parallel tasks feed into a third synthesis task
85+
analyze_task = Task(
86+
description=f"Find bugs in: {snippet}",
87+
expected_output="List of issues.",
88+
agent=analyzer,
89+
)
90+
test_task = Task(
91+
description=f"Write 3 pytest tests for: {snippet}",
92+
expected_output="Python pytest code.",
93+
agent=tester,
94+
)
95+
review_task = Task(
96+
description="Combine the above into PR feedback.",
97+
expected_output="Markdown PR comment.",
98+
agent=reviewer,
99+
context=[analyze_task, test_task], # depends on both
100+
)
101+
102+
crew = Crew(
103+
agents=[analyzer, tester, reviewer],
104+
tasks=[analyze_task, test_task, review_task],
105+
process=Process.sequential, # CrewAI parallelizes within stages
106+
)
107+
result = crew.kickoff()
108+
print(result)
109+
```
110+
111+
CrewAI executes `analyze_task` and `test_task` concurrently because
112+
they have no dependency; `review_task` runs after both finish. With
113+
Kakeya's scheduler, those two parallel calls share GPU time fairly
114+
under admission control. Against `mlx_lm.server`, they would
115+
serialize and the wall-time would roughly double.
116+
117+
## Caveats
118+
119+
- CrewAI's `LLM` config has many sampling-related fields
120+
(`temperature`, `top_p`, `frequency_penalty`, `seed`). Kakeya
121+
ignores all sampling params (greedy by design). Set them or
122+
don't — output is the same.
123+
- For very long crews (≥ 10 agents) bump `--max-concurrent` to
124+
match. Otherwise late-admitted agents wait on `queue`.
125+
- Tool calling via CrewAI's `tools=[...]` parameter works. JSON
126+
reliability depends on the verifier; Qwen3-1.7B is reasonable
127+
out of the box for simple schemas, less so for nested ones.

0 commit comments

Comments
 (0)