Skip to main content

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.

1 min read · updated

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 scopingSessionConfig.projectId + x-codespar-project header
TypeScript onlyPython 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 with codespar.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_id now 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 invoked

The 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 firesession.execute("codespar_notify", params). Synchronous, cheap, unambiguous.
  • Let the agent decidesession.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 codespar
from 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/sdk to ^0.3.0 in package.json
  • Bump every @codespar/ADAPTER package (claude, openai, vercel, etc.) to ^0.3.0 in the same commit
  • Replace codespar.sessions.create( with codespar.create(userId, across the codebase
  • Replace the old object-form session.execute calls with the two-positional form session.execute(name, params)
  • Audit every session.send call — decide: execute for a direct tool call, or pass a string message for the agent loop
  • Replace await session.mcp() with session.mcp
  • (Optional) Pass projectId on 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