This PR:
- bumps `composio` and all 13 provider distributions from `0.19.0` to
`0.20.0`, keeping `python/composio/__version__.py` and `uv.lock` aligned
with package metadata
- adds `docs/content/changelog/08-19-26-sdk-releases.mdx`, the combined
customer-facing changelog for both SDKs, documenting the session-aware
provider tool-call helpers from #4098 (Python `composio` 0.20.0,
TypeScript `@composio/core`/`@composio/slim` 0.17.0,
`@composio/anthropic` 0.11.0, `@composio/openai` 0.12.0) and the
API-response URL validation and Python file-handling fixes shipped since
the last train
- documents `@composio/core` `0.17.0` in that entry so the generated
Changesets release PR (#4161) passes the release-workflow guard
## Release sequence
1. Merge this PR.
2. Merge #4161 (the generated "Release: update version" PR) once it goes
green. Merging publishes the TypeScript packages to npm.
3. Tag the resulting `next` commit `py@0.20.0` to publish the Python
packages to PyPI.
4. Follow-up PR: bump `docs/package.json` pins to
`@composio/core@^0.17.0`, `@composio/anthropic@^0.11.0`,
`@composio/openai@^0.12.0` and remove the now-stale `@errors: 2345`
Twoslash TODO markers in the provider docs, once the npm publish lands.
## Verification
- Verified the release-workflow guard reads the new changelog rows for
Python `0.20.0` and TypeScript `@composio/core` `0.17.0`
- All 13 Python `pyproject.toml`/`setup.py` pairs bumped consistently;
`uv.lock` regenerated
## Summary
Automated documentation updates triggered by new changelog entries
merged to next.
Generated by Codex via GitHub Actions.
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Problem
Provider tool-call helpers always used the globally injected direct
`Tools.execute` function. When a model received tools from
`session.tools()`, calling `handleToolCalls` or `handle_tool_calls`
therefore discarded the Tool Router session context and caused session
meta-tools such as `COMPOSIO_SEARCH_TOOLS` to fail.
Calling `session.execute()` manually preserved the session, but bypassed
provider behavior such as Anthropic input normalization and schema-alias
restoration.
## Root fix
- Add an explicit execution target to the non-agentic provider helpers:
- TypeScript: `handleToolCalls(session, response)` and
`executeToolCall(session, call)`
- Python: `handle_tool_calls(response=response, session=session)` and
`execute_tool_call(tool_call=call, session=session)`
- Route normalized provider arguments through the supplied Tool Router
session.
- Map session responses back to each helper's existing result shape.
- Keep provider-specific normalization before execution, including
Anthropic schema-alias restoration.
- Reject direct-only options and modifiers when the selected target is a
session, including plain JavaScript calls that bypass the TypeScript
overloads.
- Update OpenAI and Anthropic examples to use the session-aware helpers.
- Harden the docs policy test so setup and execution split across fences
in one sample are still detected.
## Docs review follow-ups
- Reword the concepts-page prohibition so it forbids user-ID-bound
helper calls, not the helpers themselves, matching the provider pages in
this PR.
- Add minimum-version callouts to the OpenAI and Anthropic provider
pages (Python `composio` newer than 0.19.0; TypeScript `@composio/core`
≥ 0.17.0 with `@composio/openai` ≥ 0.12.0 / `@composio/anthropic` ≥
0.11.0), pointing older versions at `session.execute()`.
- Bump `docs/package.json` to `@composio/core` `^0.15.0` and
`@composio/openai` `^0.11.0` (the published majors at the time of the
bump; `@composio/core` 0.16.0 and `composio` 0.19.0 have since released
from `next` without this PR, so its changeset will publish core 0.17.0
and the next Python minor) and annotate each `@errors: 2345` Twoslash
marker with a TODO naming the minor version that retires it; since this
changeset releases minors, all three pins need a manual range bump to
retire the markers. This version of twoslash only throws on *unlisted*
errors, so a stale marker cannot break the build — it would only mask
future TS2345s, which the TODOs now track.
- Update `SESSION_GUARDRAILS` (the block appended to `.md` responses for
agents): add a session-execution bullet (scoped to the OpenAI and
Anthropic helpers, with `session.execute()` for every other provider)
and qualify the direct-execution list with "with a user ID". The
session-execution static test now scans the guardrail blocks like the
execute-version test already did.
- Tighten the docs detector: the Python branch is bounded to the helper
call's argument list (tolerating one level of nested calls) instead of
running past the closing paren, and the TypeScript branch catches whole
user-ID identifiers (`userId`, `user_id`, `uid`) without flagging
session variables like `userSession` — each edge has a regression test.
- Note on the Google provider page that its `executeToolCall` is not
session-aware yet.
## Compatibility and release
Existing user-ID calls remain unchanged and continue to use direct tool
execution. The new session call forms are additive.
The changeset applies minor releases to `@composio/core`,
`@composio/openai`, and `@composio/anthropic` — the new session
overloads are a type-level break for provider subclasses, so patch was
too small. The configured fixed group also includes `@composio/slim`.
The docs site intentionally checks examples against currently published
SDK declarations. The three new TypeScript calls therefore carry exact
Twoslash `TS2345` release-skew annotations; remove them (per the inline
TODOs) once `docs/package.json` picks up `@composio/core` ≥ 0.17.0,
`@composio/openai` ≥ 0.12.0, and `@composio/anthropic` ≥ 0.11.0.
## Verification
- `@composio/core`: 1,061 tests passed; typecheck passed
- `@composio/openai`: 34 tests passed; typecheck passed
- `@composio/anthropic`: 53 tests passed; typecheck passed
- Python provider and aliasing suites: 40 passed, 4 skipped
- Focused Python mypy and Ruff checks passed
- Docs static suite: 208 tests passed (including the new guardrail-scan
and detector cases)
- Docs production build passed with the bumped `@composio/core` 0.15.0 /
`@composio/openai` 0.11.0, including Twoslash, TypeScript, and all
generated pages
- Docs lint passed; lint reports only existing warnings
- Changeset status reports the expected minor packages
---------
Co-authored-by: Soumya Medapati <soumyamedapati@soumyas-air.local.meter>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: jkomyno <alberto@composio.dev>
The new AuthDiagram sized its hub (`w-36`) and account cards (`w-44`) with
fixed widths totalling 320px, but the feature-grid pane is not monotonic in
the viewport: ~404px at 1280px, and only ~242px at 640px where the grid goes
two-column. Below ~394px viewport the two blocks shrank until they touched,
`ex === sx` collapsed every wire into `elbowPath`'s straight-line fallback,
and the middle connector became a zero-length, invisible path. The card
rendered as three stray tick marks on every iPhone below Pro Max, and the
account cards overflowed the clip at 360px.
Use proportional widths with caps (`w-[36%] max-w-36` / `w-[52%] max-w-56`)
so ~12% of the pane is always reserved as horizontal run for the elbows.
Measured after: 29px gap at the 242px worst case, 34px at 360px, 50px at
1280px, no overflow and no degenerate paths anywhere in the range. The
account label now hides by container query rather than a viewport
breakpoint, which would gate on the wrong axis.
Also from review:
- Sandbox mock showed `composio.sandbox.run()` in a file chromed `sandbox.ts`.
Per content/docs/sandbox/remote.mdx — where the card links — the sandbox is
a persistent Python environment driven through COMPOSIO_REMOTE_WORKBENCH
with `run_composio_tool` / `invoke_llm`. Rewritten on that real surface and
relabelled `sandbox.py`; `WorkbenchVisual` renamed to `SandboxVisual`.
- `twilio` is not in public/data/toolkits.json, so the tile advertised an app
with no /toolkits page behind it. Swapped for `zendesk`.
- The dark logo was `aria-hidden`, so the heading's accessible name lost
"Composio" in dark mode only. Both variants now carry the same alt.
- Restored the badge style assertions the PR dropped, which still held, and
added regression coverage for the diagram widths, the catalog check, and
the sandbox surface.
- Restored the window resize listener that connection-refresh-visual.tsx
keeps alongside its ResizeObserver.
- Nits: stale "8×2" comment, redundant fragment, shared the duplicated fade
style, renamed the misleading `homeIntentAnchor(title)` parameter.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Extracting buildReferenceTree() existed only so a module-level memo could reuse
the tree. The memo is gone, so the extraction was scaffolding for nothing and
every reference-layout hunk was pure churn in a PR about adding an event.
Both files go back to their shape on next, plus the same four lines the docs and
examples layouts already take. The non-test diff is now insertions only.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
getNavIndex() awaited buildReferenceTree() on its own while Layout had already
awaited the same tree for DocsLayout, so the first render built and filtered the
reference tree twice. The memo it protected was a module-level singleton with no
key, which is what prompted removing the parameter in the first place.
Dropping the memo resolves both: the index is one traversal over ~64 nodes built
from the tree already in hand, matching how the docs and examples layouts work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The position assertions pinned absolute indices into the live content tree, so
adding any page to meta.json failed a test named for traversal semantics with
"expected 12, received 13". Assert the invariant instead — a folder occupies one
sibling slot, and its children restart at 1 — which stays green when content
moves and still fails if position starts threading through folders again.
getNavIndex(tree) ignored its argument on every call after the first. The
reference tree is only reachable after an await, so it stays memoized, but the
signature no longer claims to vary with a parameter it never read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Show the actual six-line quickstart snippet (`import Composio` + `import OpenAIAgentsProvider` + `new Composio({ provider })` + `composio.create(userId)` + `session.tools()` + `new Agent({ … })`), tightened to 11.5px / 1.75 leading so it fits inside the same left-pane height as the For You card.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two-ways-to-start hero: cards now lead with the canonical Composio + product-badge lockup (dashboard-parity) and the same product mocks the dashboard onboarding path step uses — a chat composer flanked by client logos for For You, a code panel for Platform. Right link pane width matches a feature-grid card exactly.
Features grid: whole-card links restored, each mock fades into the card edge with a mask-image, cards live on a single flush bg-fd-card surface. Tools mock bumps from an 8×2 grid of 16 tiles to 10×3 = 30 for more impact, Auth becomes a live schematic — one user identity card wired to three connected-account cards via elbow connectors computed from real DOM geometry (`home-auth-diagram.tsx`), Triggers drops the fake LIVE ping in favor of a plain event list, Sandbox drops the workbench chrome + CPU lights for a clean filename + code panel.
Resources: adds a Platform Dashboard link so the 3×2 grid is complete. Drops the "Get started / What you get / Reach for the rest" eyebrows and section heading — headings stand on their own.
Copy: `audience` → `product`, so llms.txt emits `**Platform**` / `**For You**` instead of `**Platform**` / `**For you**`; matched in `home-navigation.test.ts`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Review follow-ups on the docs_sidebar_click instrumentation.
usePostHog() resolves to the posthog-js module singleton whether or not a
provider is mounted, so the `!posthog` guard never fired: with no
NEXT_PUBLIC_POSTHOG_KEY the listener still attached and every sidebar
click called capture() on an uninitialized instance, logging "You must
initialize PostHog before calling posthog.capture". Gate the effect on
the same env var components/posthog-provider.tsx gates on.
position threaded through folder recursion, so a collapsed folder's
hidden children counted as rows: Triggers is the 4th visible row under
Core concepts but reported 11, which would inflate any "clicks land in
the top N rows" reading — the same inference error this instrumentation
exists to remove. Count per level instead, so a folder occupies one row
for its siblings and its children get their own 1..n sequence. Making
group and position per-level locals also removes the latent collision
where a separator nested in a folder reset the counter for the folder's
siblings; a test pins that case.
Also: capture auxclick (middle button only) so sidebar links opened in a
new tab are not missing while Cmd/Ctrl+click ones are counted; a folder
with a non-string name now reports folder: null rather than inheriting
its parent's label; and both reference layouts memoize the index instead
of rebuilding it on every render.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The docs app had exactly one posthog.capture call ($pageview), so any
question about how people move through the sidebar had to be answered by
reverse-engineering pageview ordering within a session. $referring_domain
is no help either: pageviews are captured manually on client-side route
change, so document.referrer never updates on internal navigation.
Adds a docs_sidebar_click event carrying href, group, folder, depth,
position and from_path. Group/folder/depth are derived from the fumadocs
page tree at build time and the click handler only does an href lookup —
reading them off the rendered sidebar would mean depending on separators
being <p> and folder triggers being <button>, which is fumadocs-internal
and breaks on upgrade.
Mounted on the docs, examples and both reference sidebars. Nothing fires
when PostHog is unconfigured, for non-sidebar links, or for an href that
is not in the index.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Revert the separator split, and the later ---Security--- rename with it.
Each half held exactly one folder whose title near-repeats the heading,
so the sidebar read "Migration" / "Migration guides" and "Security" /
"Security and data", and llms.txt emitted "## Security" immediately
above "### Security and data". content/docs/meta.json is byte-identical
to next again; both folders keep their titles.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four review fixes on the sidebar restore.
Folder headings do not close, so every page emitted after a folder read
as one of that folder's children. Making `authentication` a folder
mid-list swallowed `triggers` and `skills` into `### Authentication`.
Reordering meta.json would fix the output but push Authentication below
Skills in the human sidebar, which is what this PR exists to prevent —
so walkPageTree now buffers each separator section and flushes its plain
pages ahead of its folders. Legacy-separator skipping is unchanged. This
also fixes the pre-existing case where `agent-plugins`, `cli` and
`composio-connect` read as children of `#### Custom providers`.
Drop "index" from authentication/meta.json. Listing it clears
`node.index`, so fumadocs renders the folder as a chevron BUTTON plus a
duplicate child row instead of a SidebarFolderLink — the row a reader
clicks to reach /docs/authentication (1,850 views/month) expanded the
folder instead of navigating. Omitting it matches how `providers` and
`migration-guide` already render. Verified in the built DOM: an A with
href=/docs/authentication, no duplicate row, /docs/authentication.md
still emitted exactly once via node.index.
Rename the ---Security and data--- separator to ---Security---; it
duplicated the folder title directly beneath it, in llms.txt and in the
sidebar.
Point the last three agent/instructions/context.md bullets at canonical
paths rather than redirect-only /docs/authenticating-users/* ones, so
that file is internally consistent.
Extend the llms.txt section test to assert the nearest preceding heading
of any level, and to cover the sibling pages that regressed. It fails
against the old walk.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two review follow-ups:
- Revert docs/lib/standup-bot-source.json. It is an upstream source
snapshot that gets regenerated, so editing the doc URL in that code
comment only desyncs it and would be clobbered anyway. The permanent
redirect covers the stale path.
- Strengthen the agent-reachability assertion in start-routing.test.ts.
Asserting meta.json membership alone is weaker than the assertion it
replaced, which checked a string that actually shipped into llms.txt:
a break in the page-tree walk would have gone unnoticed. Import the
llms.txt route handler and assert its generated output — each of the
8 guide URLs present exactly once, the 7 auth guides under Core
concepts -> Authentication, shared-connections under Guides -> Extend
sessions, and no trailing "## Authentication guides" section. Follows
the existing tests/static/llms-openapi.test.ts pattern of importing an
app route directly, so it runs in `bun run test` with no server.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR #4099 dropped 8 auth pages from meta.json. That was a net win for
machines (Loop 5 eval: 84/100 vs 77/100, tool-routing failure mode gone)
but it made the pages unreachable by clicking. PostHog, weekday-matched
and control-adjusted, shows the affected pages down 14-64pp beyond the
site-wide baseline drift.
Restore human navigation without touching the machine-facing wins:
- authentication.mdx becomes authentication/index.mdx and the 7 sibling
auth pages move into the folder. /docs/authentication keeps its URL
(fumadocs serves index.mdx at the folder route), so Core concepts
still shows one row and the top-level sidebar row count stays 20.
- shared-connections moves into extending-sessions: it is experimental
and is a session capability, not a core auth concept.
- "Migration and security" splits into "Migration" and "Security and
data" — separator headings, not clickable rows.
- Drop AUTHENTICATION_GUIDE_URLS from app/llms.txt/route.ts. The pages
are back in the page tree, so they emit automatically under Core
concepts -> Authentication; the hardcoded list would now duplicate.
- 8 permanent redirects for the old URLs (36-42% Google entry rate on
most of them), plus existing redirect destinations repointed so none
of them chain.
- ~90 inbound links rewritten across content, api-overviews, app, lib
and agent instructions. lint:links is the gate: 0 errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
## Summary
Automated sync of backend data into the docs site. Triggered by:
`schedule`.
## What changed
- **Toolkit catalog** (`docs/public/data/toolkits.json`,
`toolkits-list.json`) — refreshed list of available toolkits, auth
schemes, and tools from the backend API
- **OpenAPI specs** (`docs/public/openapi.json`,
`docs/public/openapi-v3.json`, `docs/public/openapi-webhooks.json`) —
latest v3.1 and v3.0 API specifications plus the webhook-events spec,
fetched from production
- **API reference pages** (`docs/content/reference/api-reference/`,
`docs/content/reference/v3/api-reference/`) — regenerated index pages
for both API versions
- **Meta tools reference** (`docs/public/data/meta-tools.json`,
`docs/content/toolkits/meta-tools/*.mdx`) — updated meta tool schemas
and reference docs
Co-authored-by: Sushmithamallesh <19796925+Sushmithamallesh@users.noreply.github.com>
Custom MCP hardening docs pass from Pelago feedback (Linear PLEN-2931,
origin PLEN-2927), verified against platform code on master.
- Auth config: state explicitly that registration does not create an
auth config; for API-key and DCR OAuth servers creating one (with
`is_enabled_for_tool_router: true`) is a required separate step. Also
fixed the PATCH example: the update body requires `"type": "custom"`
(discriminated union), the previous example would 400.
- v3 gotcha: explain the empty-tools-list symptom, `GET
/api/v3/tools?toolkit_slug=CUSTOM_...` pins a default version without
custom tools; pass `toolkit_versions=latest` or use v3.1.
- Upsert semantics refresh (tracks platform #11598): re-registering an
owned slug now updates mutable fields (name, logo) in place, identical
config is a no-op; `app_url` and `auth_schemes` stay immutable (409,
delete + re-register). Updated the registration callout, logo section,
delete section, and known gaps.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
Automated sync of backend data into the docs site. Triggered by:
`schedule`.
## What changed
- **Toolkit catalog** (`docs/public/data/toolkits.json`,
`toolkits-list.json`) — refreshed list of available toolkits, auth
schemes, and tools from the backend API
- **OpenAPI specs** (`docs/public/openapi.json`,
`docs/public/openapi-v3.json`, `docs/public/openapi-webhooks.json`) —
latest v3.1 and v3.0 API specifications plus the webhook-events spec,
fetched from production
- **API reference pages** (`docs/content/reference/api-reference/`,
`docs/content/reference/v3/api-reference/`) — regenerated index pages
for both API versions
- **Meta tools reference** (`docs/public/data/meta-tools.json`,
`docs/content/toolkits/meta-tools/*.mdx`) — updated meta tool schemas
and reference docs
---------
Co-authored-by: Sushmithamallesh <19796925+Sushmithamallesh@users.noreply.github.com>
Co-authored-by: jkomyno <alberto@composio.dev>
Reverts the quickstart portion of #4099, which replaced the framework
picker (OpenAI Agents, Claude Agent SDK, Vercel AI SDK with Python and
TypeScript tabs) with a Python-only uv flow, leaving TypeScript readers
without a quickstart path.
Keeps the parts of #4099 that improved the page:
- Sharper intro and meta-tools explanation
- Agent instructions that handle Connect Links and confirm destructive
actions, applied to all six code samples (the Claude Agent SDK
TypeScript sample previously had no system prompt)
- "What just happened?" section, dual-language session persistence notes
- Production callout for replacing user_123 with a stable user ID
- Logs API pointer and "Adapt the example" cards
Deletes tests/static/quickstart.test.ts, which was added by #4099 to pin
the Python-only structure.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Applied the repo's good-docs-writing skill. The page broke its two hardest
rules: em-dashes are banned in this style and the page was built on them
(the sibling triggers page has zero), and a page with no example asked the
reader to take the whole mechanism on trust.
It now shows the search response carrying a plan, so the shape is concrete
before the prose explains it. The field names are checked against the
schema in composio_actions/utils/schemas.ts: recommended_plan_steps and
known_pitfalls are string arrays, difficulty is a string, and all three are
optional, present only when a skill covers the use case. The page says so,
since anything else would have readers destructure fields that may be absent.
Also cut the filler the audit checklist flags and made every definition a
sentence rather than a dash fragment.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
## Summary
- Reframes the docs Welcome page around two intents: build with Composio
or use Composio from an existing agent.
- Replaces the framework picker with a general Python quickstart and
routes other frameworks to focused provider guides.
- Adds a shared Agent plugins page for Codex and Claude Code, with
CLI-first setup and explicit MCP alternatives.
- Simplifies the sidebar into Get Started, Core concepts, Guides, Direct
execution (legacy), and Migration and security.
- Keeps the Welcome page readable through its `.md` endpoint and
clarifies intent routing in `llms.txt`.
## Review order
1. Welcome hero and the two intent cards.
2. Quickstart copy and runnable example.
3. Agent plugins, CLI, and MCP routing.
4. Sidebar grouping and progressive disclosure.
5. Agent-readable Welcome Markdown and regression tests.
## Validation
- `bun run test` — 208 passing
- `bun run types:check`
- `bun run lint:links` — 0 errors
- `bun run lint` — passes with pre-existing warnings only
- Dashboard badge styles compared against the live product UI
## Deliberately out of scope
- Docs eval harnesses or eval result files
- Search ranking, agent-index generation, or agent prompt changes
- Deleting pre-existing unused hero or quickstart components
- Unrelated lint warnings and docs content cleanup
This replaces #4085 with a one-commit, docs-only review surface. The
earlier PR accumulated implementation experiments and bot commentary
that made the intended change difficult to evaluate.
## Summary
- clarify that the SDK fetching examples default to `latest`
- distinguish REST v3 pinned defaults from REST v3.1 latest defaults
- replace the blanket production warning with output-consumer guidance
## Root cause
The legacy fetching guide used an unqualified `API` statement next to
SDK examples. That conflated SDK behavior with two REST API versions and
contradicted the current API reference.
No SDK package changes or changeset are required.
This PR:
- builds on top of https://github.com/ComposioHQ/composio/pull/4094
- bumps `composio` and all 12 provider distributions from `0.18.2` to
`0.19.0`
- keeps `python/composio/__version__.py` and `uv.lock` aligned with
package metadata
- documents recursive provider argument-presence preservation in the
existing cross-SDK changelog
- passes the release-workflow guard, Ruff, mypy, provider type
inference, and 1,167 Python tests
- builds and validates 26 wheel/sdist artifacts with Twine
- must be retargeted to `next` after #4094 merges
The catalog is gated to selected orgs, so pointing every reader at a Skills
tab most of them cannot see would send them looking for a nav item that
isn't there. The capability itself is not gated — skills already reach every
org through the search response — so the rest of the page stands on its own.
The section was also stale on its own terms: it advertised app chips showing
per-toolkit counts, which read the catalog-stats endpoint that has since been
removed, and described browse ordering as "maturity / most-refined" after the
list was changed to say most used.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
compileToolInputSchema still runs inside validateToolInputArgumentsWithDefinition,
so the failure fires on every invocation. What changed is the diagnosis, not the
frequency. Line 153 already made only the diagnosis claim; this aligns line 88 and
the matching CLI changelog line with it.
The previous wording claimed both SDKs surfaced an invalid dynamic-key
schema only when validation descended into it. That is the CLI's lazy
interpreter; Python never read the keywords, so the defect never surfaced
and the new raise is unconditional at wrap time, not payload-dependent.
Also add @composio/slim to the versions table: it is public and in the
fixed Changesets group with @composio/core, so it ships this fix at the
same minor.
Both SDKs surfaced an invalid dynamic-key schema only when validation
descended into it, so a payload that stayed out of the affected branch
ran against a schema that could not fully validate it. Failing at the
schema is the point, but it is a behavior change and the entry framed it
as affecting only already-failing input.
The open-by-default claim and the Backward Compatibility carve-out both
read as unconditional for objects that name no properties. An explicit
additionalProperties: false closes such an object, and Python raises on
unknown keys it previously dropped through Pydantic's default
extra="ignore" - the same drop-to-raise transition already documented
for objects that declare properties.
The wrap-time paragraph named only Python. The CLI now fails the same way
on the two defects its validator can detect, so both the dynamic-keys
section and Backward Compatibility say which SDK does what, and note that
a reference outside a dynamic-key subschema is still left alone.
The Backward Compatibility carve-out claimed objects declaring no
properties were unaffected. On next, the Python converter read neither
patternProperties nor schema-valued additionalProperties, so those
objects became empty Pydantic models and every dynamic key was dropped
in silence. Those keys are now validated and can raise ValidationError.
Document it as the third call-time behavior change, with before/after,
narrow the carve-out to objects with no dynamic-key constraints, and
note that the prior 'unrelated pattern' behavior was TypeScript-only.
Prepares the next SDK train: Python `composio` `0.18.2` and the
TypeScript packages that the pending Changesets will publish
(`@composio/core` and `@composio/slim` `0.15.0`, `@composio/openai`
`0.11.0`, `@composio/experimental` and `@composio/json-schema-to-zod`
`0.2.2`).
No CLI release is part of this train.
## What this PR does
- bumps Python core and all 13 provider packages to `0.18.2`, including
`python/composio/__version__.py` and the root plus per-provider
`uv.lock` files
- adds `docs/content/changelog/08-07-26-sdk-releases.mdx`, the combined
customer-facing changelog for both SDKs
- documents `@composio/core` `0.15.0` in that entry so the generated
release PR passes the release-workflow guard
- leaves the pending Changesets untouched; the generated release PR
remains responsible for npm versioning and publication
## Release sequence
1. Merge this PR.
2. Let Changesets regenerate the "Release: update version" PR, wait for
it to go green, then merge it. Merging publishes the TypeScript
packages.
3. Tag the resulting `next` commit `py@0.18.2` to publish the Python
packages to PyPI.
## Notes
- The root `uv.lock` diff carries ~28 lines of marker-annotation churn
beyond the version bumps. That is the repo-pinned `uv` `0.8.19`
normalising markers the committed lockfile had recorded differently; no
dependency versions change.
- `@composio/mastra` and the TypeScript providers are unchanged: their
declared peer ranges still accept `@composio/core` `0.15.0`, so
Changesets does not bump them.
## Verification
- `pnpm test:release-workflow` — passes (Python package, runtime, and
provider versions agree; both SDK versions documented in the changelog)
- `uv run pytest tests/` in `python/` — 925 passed, 35 skipped
- `uv run --package composio python -c "import composio"` — reports
`0.18.2`
- `bun test tests/static/` in `docs/` — 195 pass, 1 pre-existing failure
(`getLLMText — version pointer`, also fails on a clean tree)
- `bun run types:check` in `docs/` — MDX generation and route typegen
succeed; the final `tsc` step could not run locally because
`typescript-7` is absent from `docs/node_modules`
This PR:
- fixes
[UXE-233](https://linear.app/composio/issue/UXE-233/docs-should-explicitly-direct-agents-to-use-v31-apis)
- makes the agent-facing Markdown channels publish concrete REST v3.1
base URLs and endpoint tables while preserving the supported v3.0
reference tree
- centralizes `REST_VERSION_GUIDANCE`, `TOOL_VERSION_GUIDANCE`, and
raw-spec path matching in `lib/api-version-guidance.ts`
- renders `ApiBaseUrl` and `ApiEndpointsTable` in authored MDX and adds
an explicit version pointer to generated OpenAPI operation Markdown
- separates current and legacy REST references in `llms.txt`, excludes
v3.0 page bodies from `llms-full.txt`, and adds v3.1 selection guidance
to Context7
- validates serialized `ApiEndpointsTable` payloads with Zod before
generation while preserving forward-compatible fields
- addresses review feedback for the renamed authentication page,
SDK-reference pointer scope, generator validation behavior, and stale
OpenAPI tool-version descriptions
## Context
REST v3.0 is superseded but remains supported for existing integrations.
This PR changes what new agent-generated code discovers first; it does
not require existing v3.0 callers to migrate.
Authenticated read-only probes against the deployed API confirmed that
the affected v3 endpoints default to `00000000_00`, while their v3.1
counterparts default to `latest`. `POST /tools/scopes/required` is
available only on v3.1 and defaults to `latest`.
This PR does not move public URLs. A future `/reference/v3/` to
`/reference/v3.0/` migration remains separate because it has independent
compatibility and search-indexing risk.
## Verification
- `bun test tests/static/`
- `bun run build`
- `bun run test:integration`
- `bun run types:check`
- `bun run lint`
## Review follow-up
The version-default guidance is intentionally limited to the five
verified tool endpoints. v3.1 is a structural superset of v3, so this PR
does not claim route parity. Static coverage rejects broad non-tool
parity wording in both the shared guidance and Context7 rules.
## What
In three independent eval runs across two rounds
(ctx.composio.io/soumya/docs-agent-eval/), capable agents classified
this block as prompt injection and deliberately ignored it (round 1,
agent-007: "a prompt injection I had to identify and ignore"; round 3,
two more agents unprompted). The ALWAYS/NEVER imperative framing also
contradicted the sessions-vs-direct-execution page — the block forbade
the API that page documents.
## Change
Rewritten in `docs/lib/llm-guardrails/session.ts` — same facts, no
commands:
- Sessions documented as the recommended default (samples unchanged)
- The provider-import gotcha kept — it's the most common real mistake in
generated code
- The managed-auth default kept
- Direct execution acknowledged as a supported lower-level interface,
with a link to the sessions-vs-direct tradeoffs page (this replaces the
"DISCOURAGED — do not generate tools.execute()" section, which
contradicted the docs one click away)
An AI-steering block only works if AI readers trust it.
## Verification
- `bun test tests/static/` passes (the execute-version policy test also
validates the guardrail blocks)
- Every factual claim from the old block is preserved; only the framing
and the tools.execute() discouragement changed
Split out of #4059 (which now carries only the legacy-flag and
REST/SDK-naming changes) so this piece can be decided on its own.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Three independent eval runs across two rounds show capable agents
classify the CRITICAL INSTRUCTIONS block as prompt injection and ignore
it; its ALWAYS/NEVER framing also contradicted the
sessions-vs-direct-execution page. Same facts, no commands: sessions
stay the recommended default, the provider-import gotcha and
managed-auth default are kept, and direct execution is acknowledged as a
supported lower-level interface with a link to the tradeoffs page.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>