Skip to content

feat(sdk): extract Fern Python client to clients/python package#4255

Closed
mmabrouk wants to merge 2 commits intochore/sdk/relocate-to-sdks-pythonfrom
feat/sdk/python-fern-client
Closed

feat(sdk): extract Fern Python client to clients/python package#4255
mmabrouk wants to merge 2 commits intochore/sdk/relocate-to-sdks-pythonfrom
feat/sdk/python-fern-client

Conversation

@mmabrouk
Copy link
Copy Markdown
Member

@mmabrouk mmabrouk commented May 4, 2026

Summary

The generated Fern Python client previously lived inside the SDK tree
at sdk/agenta/client/backend/, coupling the handwritten SDK and the
generated client by package path rather than by API contract. This
extracts the generated client into a standalone clients/python/
package exposing AgentaApi, AsyncAgentaApi, AgentaApiEnvironment,
and ~100+ Pydantic DTO types.

A bridge in sdks/python/agenta/client/__init__.py replaces
sys.modules entries so all existing
from agenta.client.* import ... imports continue to work unchanged.
No consumer migration is required.

What changed

Adds:

  • clients/python/agenta_client/ — the standalone Fern-generated
    Python client (~752 files: clients, types, errors, environment)
  • clients/scripts/generate.sh — regen entrypoint with
    --openapi-url <URL> and --openapi-file <path> modes. Also
    contains a Python post-processor (fix_typescript_admin_duplicates)
    that renames the duplicate createAccounts method generated by
    Fern. The duplicate is now also fixed at the source via
    include_in_schema=False (PR
    fix/api/admin-accounts-openapi); the post-processor remains as a
    belt-and-suspenders for older OpenAPI specs.
  • sdks/python/oss/tests/test_fern_client.py — structure tests that
    validate all client imports, instantiation, and sub-module presence
    (no API calls)
  • clients/python/{pyproject.toml,README.md} and clients/README.md
  • ruff.toml — excludes clients/ from ruff (Fern-generated)
  • .pre-commit-config.yamlexclude: ^clients/ on the ruff hooks
  • docs/designs/fern-clients/{proposal,plan,research,gap}.md
    design notes
  • Updates to existing design docs (docs/design/chat-interface-rfc/,
    docs/design/fern-sdk-update/) referencing the new generate.sh path

Removes:

  • sdk/agenta/client/* — old generated client artifacts that don't
    have a one-to-one mapping in the new package, plus a 95-file cleanup
    of stale generated files

Diff

  • 825 files changed, 119,618 insertions, 11,755 deletions
  • Stat-skewed by Fern-generated code under clients/python/agenta_client/
    (excluded from ruff/pre-commit per the ruff.toml and
    .pre-commit-config.yaml changes in this PR)

Commits

2 commits, kept separate due to a GitButler squash conflict around
rename detection. Squash-merge recommended:

  1. feat(sdk): extract Fern Python client to clients/python package
  2. chore(sdk): remove obsolete sdk/agenta/client/* artifacts
    (split-commit complement to the extraction)

Risks

  • Bridge shim correctness: sdks/python/agenta/client/__init__.py
    uses sys.modules rewriting to map agenta.client.*
    agenta_client.*. This is the load-bearing piece. Test coverage
    is in sdks/python/oss/tests/test_fern_client.py which validates
    imports, instantiation, and sub-module presence.
  • Type compatibility: the new agenta_client.* types may have
    field-by-field equivalents but renamed Pydantic class identities
    vs the old agenta.client.backend.types.*. If any consumer imports
    a type and uses isinstance() against it, that check could break
    silently. Grep for isinstance(..., backend\.types\. usages and
    verify before merging.
  • Fern regeneration is not yet wired into CI — the script exists
    but is run manually. A future PR should add a CI guard that fails if
    the committed clients/python/ differs from a fresh regen against
    the OpenAPI spec.
  • Generated code is excluded from lint — by ruff.toml and the
    pre-commit config. This is intentional but means ruff will not catch
    drift between hand-written and generated code at the package
    boundary.

QA

  • CI green
  • pip install -e sdks/python && pip install -e clients/python
    installs both packages
  • python -c "from agenta.client.backend import AgentaApi; print(AgentaApi)"
    — should resolve via the bridge to agenta_client.AgentaApi
  • python -c "from agenta_client import AgentaApi" — direct
    import works
  • pytest sdks/python/oss/tests/test_fern_client.py — all
    structure tests pass
  • Run the full SDK test suite: cd sdks/python && pytest oss/tests/
    — confirms no regression in consumers that still import via
    agenta.client.*
  • Spot-check: import a type that was used downstream (e.g.
    from agenta.client.backend.types.config_dto import ConfigDto)
    and confirm it loads
  • Regenerate the client from a local OpenAPI:
    bash clients/scripts/generate.sh --openapi-file ./openapi.json
    — should produce a no-op diff against committed
    clients/python/
  • Run ruff check from repo root — confirm clients/ is excluded

Notes

  • Stacked on chore/sdk/relocate-to-sdks-python (which is itself
    stacked on chore/infra/per-service-container-workdir).
  • Originally part of [chore] Review and cleanup fern #4239 — split out for independent review.
  • Benefits from PR fix/api/admin-accounts-openapi (which removes
    the duplicate createAccounts at the OpenAPI source). That PR is
    parallel against main; its removal of the duplicate eventually
    lets us drop the post-gen rename patch in clients/scripts/generate.sh.

mmabrouk added 2 commits May 4, 2026 12:48
The generated Fern Python client previously lived inside the SDK tree
at sdk/agenta/client/backend/, coupling the handwritten SDK and the
generated client by package path rather than by API contract. This
extracts the generated client into a standalone clients/python/
package exposing AgentaApi, AsyncAgentaApi, AgentaApiEnvironment, and
~100+ Pydantic DTO types.

A bridge in sdks/python/agenta/client/__init__.py replaces sys.modules
entries so all existing `from agenta.client.* import ...` imports
continue to work unchanged - no consumer migration required.

Adds:
  - clients/python/agenta_client/ - generated standalone Python client
  - clients/scripts/generate.sh - regen entrypoint (--openapi-url or
    --openapi-file), with a Python post-processor that renames
    duplicate TypeScript createAccounts methods (workaround for a
    route collision now also fixed at source via include_in_schema=False)
  - sdks/python/oss/tests/test_fern_client.py - structure tests that
    validate imports, instantiation, and sub-module presence (no API
    calls)
  - ruff.toml + .pre-commit-config.yaml exclude clients/ from lint and
    format (Fern-generated code)
  - docs/designs/fern-clients/{proposal,plan,research,gap}.md - design
    notes
  - Design doc updates referencing the new generate.sh path

Removes:
  - sdk/agenta/client/* - old generated client artifacts purged in
    favor of the standalone clients/python package
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment May 4, 2026 10:56am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: da26157e-e361-4916-ba29-83ac445561ec

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sdk/python-fern-client

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. python Pull requests that update Python code refactoring A code change that neither fixes a bug nor adds a feature SDK labels May 4, 2026
@mmabrouk
Copy link
Copy Markdown
Member Author

mmabrouk commented May 4, 2026

Superseded by re-sliced PRs that fix CI failures. See new PR layout for details.

@mmabrouk mmabrouk closed this May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Pull requests that update Python code refactoring A code change that neither fixes a bug nor adds a feature SDK size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant