SDK v0.2 → v0.3
Breaking changes in @codespar/sdk@0.3.0 and how to migrate an existing 0.2 codebase. Create / execute / send signatures changed; 2-level tenancy shipped.
Migration — SDK v0.2 → v0.3
@codespar/sdk@0.3.0 is a breaking release aligned end-to-end with the backend's canonical wire contract. Every framework adapter (@codespar/claude, @codespar/openai, @codespar/vercel, etc.) was bumped to 0.3.0 in lockstep. This page walks through each change and shows the before / after for real code.
The 0.2 line stays on npm — your production code will not break until you bump. We recommend upgrading in one PR per service, against sandbox (csk_test_) first, then production.
Summary of breaking changes
| Before (0.2) | After (0.3) |
|---|---|
codespar.sessions.create({ servers }) | codespar.create(userId, { servers }) |
session.execute({ name, arguments }) | session.execute(name, params) |
session.send({ name, arguments }) (fire-and-forget tool call) | session.send(message) (natural-language agent loop) |
session.sendStream({ name, arguments }) | session.sendStream(message) (streams agent events) |
session.mcp() (method) | session.mcp (property) |
| No project scoping | SessionConfig.projectId + x-codespar-project header |
| TypeScript only | Python published on PyPI (codespar>=0.1.1) |
Everything else (tool result shapes, session.tools, session.connections, session.close, session.authorize, session.findTools) is unchanged.
1. Session creation takes a userId first
The session is now scoped to an end-user. Credentials, audit logs, and billing all attach to that ID.
Before
const session = await codespar.sessions.create({
servers: ["stripe", "mercadopago"],
});After
const session = await codespar.create("user_123", {
servers: ["stripe", "mercadopago"],
});Pass a real identifier from your own system (Clerk userId, Supabase auth ID, the end-customer's email hash — whatever uniquely maps to the human on whose behalf the agent acts). For server-side jobs, pick a stable synthetic ID like "cron-worker" or "webhook-processor".
Migration strategy
- Search your codebase for
sessions.create(— replace each call withcodespar.create("user_123", ...)(use your real user ID). - Where your backend already has an authenticated user context, pipe it through instead of hardcoding.
- The
user_idnow also flows into tool-call logs and is filterable in the dashboard, which helps for per-user debugging.
2. session.execute takes two positional args
No more { name, arguments } object.
Before
const result = await session.execute({
name: "codespar_pay",
arguments: {
method: "pix",
amount: 15000,
currency: "BRL",
},
});After
const result = await session.execute("codespar_pay", {
method: "pix",
amount: 15000,
currency: "BRL",
});The return shape is unchanged — same success, data, error, duration, server, tool, tool_call_id, called_at.
Adapter helpers keep working
handleToolUse (Claude), handleToolCall (OpenAI), and the framework adapters internally call session.execute — they shield you from the signature change. If you only use adapter helpers, no code-level migration is needed beyond bumping package versions.
3. send / sendStream now drive a natural-language agent loop
This is the biggest semantic shift. In 0.2 these were fire-and-forget and streaming variants of execute — taking a tool name + arguments. They are not.
In 0.3 they take a plain-text message. The backend runs a Claude tool-use loop against the session's connected servers and returns the final response plus every tool call the agent made along the way.
Before (does not work in 0.3 — throws at compile time)
await session.send({
name: "codespar_notify",
arguments: { channel: "whatsapp", to: "+55...", template: "receipt" },
});After — if you wanted an async tool call
Use session.execute — same effect without the "queued" indirection:
await session.execute("codespar_notify", {
channel: "whatsapp",
to: "+55...",
template: "receipt",
});After — if you want the natural-language agent loop (0.3's new primitive)
const result = await session.send(
"Send a receipt to +5511999887766 via WhatsApp",
);
console.log(result.message); // agent's final response
console.log(result.tool_calls); // every tool the agent invokedThe same applies to sendStream — yields an async iterable of StreamEvent values with assistant_text, tool_use, tool_result, done, error types.
Audit the difference
In 0.2, send was often used for "fire the notification and don't care about the response." In 0.3 you have two ways to express that:
- Just fire —
session.execute("codespar_notify", params). Synchronous, cheap, unambiguous. - Let the agent decide —
session.send("Tell them their order shipped"). Useful when the message template is LLM-generated.
4. session.mcp is a property, not a method
In 0.2 you called await session.mcp() to get the MCP endpoint config. In 0.3 it is a property on the session object that is set at creation time.
Before
const mcpConfig = await session.mcp();
// { transport, url, tools }After
console.log(session.mcp);
// { url, headers }The returned shape changed too — it is now just the endpoint URL + auth headers, which is what MCP clients (Claude Desktop, Cursor) actually consume. The tools list is available via session.tools() as it always was.
5. 2-level tenancy via projectId
Organization → Project is now a first-class tenancy dimension. Sessions (and all downstream artifacts) live in one project.
SDK
const session = await codespar.create("user_123", {
servers: ["stripe"],
projectId: "prj_a1b2c3d4e5f6g7h8",
});HTTP
curl -X POST https://api.codespar.dev/v1/sessions \
-H "Authorization: Bearer csk_live_..." \
-H "x-codespar-project: prj_a1b2c3d4e5f6g7h8" \
...If you omit projectId / the header, the backend resolves to the organization's default project (auto-created at signup). Existing 0.2 traffic continues to land there automatically — no data migration needed.
See Projects for the full tenancy model.
6. Python package on PyPI
New in 0.3 — not a breaking change, but if you were waiting for Python support:
pip install codesparfrom codespar import CodeSpar
cs = CodeSpar() # reads CODESPAR_API_KEY
with cs.create("user_123", preset="brazilian") as session:
result = session.execute("codespar_pay", {"method": "pix", "amount": 15000, "currency": "BRL"})Sync (CodeSpar) and async (AsyncCodeSpar) flavours ship in the same wheel. See Quickstart (Python).
Framework adapters
Every adapter was bumped to 0.3.0 in lockstep:
npm install @codespar/sdk@^0.3.0 @codespar/claude@^0.3.0
# or
npm install @codespar/sdk@^0.3.0 @codespar/openai@^0.3.0
# ...The adapter surfaces (getTools, handleToolUse, handleToolCall, toClaudeTool, toOpenAITool, etc.) did not change — same function names, same return shapes. The version bump is to align the peer-dep against @codespar/sdk@^0.3.0.
Checklist
- Bump
@codespar/sdkto^0.3.0inpackage.json - Bump every
@codespar/ADAPTERpackage (claude, openai, vercel, etc.) to^0.3.0in the same commit - Replace
codespar.sessions.create(withcodespar.create(userId,across the codebase - Replace the old object-form
session.executecalls with the two-positional formsession.execute(name, params) - Audit every
session.sendcall — decide:executefor a direct tool call, or pass a string message for the agent loop - Replace
await session.mcp()withsession.mcp - (Optional) Pass
projectIdon session creation if you want explicit project scoping - Run the test suite against a sandbox
csk_test_key before swapping production keys
Troubleshooting
Argument of type 'string' is not assignable to parameter of type SessionConfig
— You have codespar.sessions.create(...) somewhere. sessions is gone; use codespar.create(userId, config) directly.
Type ToolCallInput is not assignable to parameter of type string (on a session.send(...) call)
— session.send now takes a string message. If the call used to be a tool invocation, switch to session.execute(name, params).
"codespar.sessions is not a function" — Same as above, at runtime. TypeScript should have caught it — double-check your build.
Adapter import fails with peer-dep warning
— Your lockfile is pinning @codespar/sdk@^0.2.0. Run npm install @codespar/sdk@latest @codespar/claude@latest (or whichever adapter you use) to upgrade both together.
Next steps
Last updated on