Skip to content

Design: chat/ai subpath port (vercel/chat#492) #109

Description

@patrick-chinchill

Status (updated 2026-05-28)

Decision: pivot to pydantic-ai-only. chinchill-api is our only consumer of chat/ai and uses pydantic-ai exclusively. This collapses the original 3-SDK shared-core design into a single pydantic-ai-native implementation.

Revised design

Pydantic is a hard dep of pydantic-ai, so we can use Pydantic models directly instead of hand-rolling JSON Schema dicts — simpler code, native pydantic-ai integration, less drift risk.

  • chat_sdk/ai/messages.py — existing to_ai_messages (moved from ai.py)
  • chat_sdk/ai/tools.py — 17 tool factories as async callables. Each takes a Chat and returns a pydantic-ai Tool (or our own thin wrapper that produces one). Input schemas as Pydantic v2 models.
  • chat_sdk/ai/orchestrator.py — create_chat_tools(chat, preset=None, require_approval=True, overrides=None). Presets (reader / messenger / moderator), per-tool overrides with whitelist.
  • chat_sdk/ai/__init__.py — re-exports to_ai_messages, create_chat_tools, individual tool factories. Deprecation shim at old chat_sdk.ai import path.
  • Optional extra: chat-sdk-python[ai] adds pydantic-ai>=0.0.X. Lazy-import inside the module.

Dropped from original design: bespoke Anthropic + OpenAI adapter modules (~120 LOC + 250 LOC tests + the cross-SDK schema-shape parity test). pydantic-ai itself handles routing to Anthropic / OpenAI / Bedrock / etc. via its model layer.

Revised effort estimate (3 PRs, ~5 days)

PR Scope LOC src / test Days
1 Move ai.py → ai/messages.py; chat_sdk/ai/__init__.py re-exports with deprecation shims ~100 / ~50 0.5
2 Core: ai/tools.py (17 factories with Pydantic input schemas), ai/types.py, ai/orchestrator.py (presets, override whitelist) ~600 / ~700 3.5
3 Docs + 1 example script (chinchill-api-style usage with pydantic-ai) — 1

Open questions (resolved)

  1. Anthropic-first vs OpenAI-first vs both → pydantic-ai only.

  2. JSON Schema dicts vs Pydantic → Pydantic v2 (already a transitive dep via pydantic-ai).

  3. Approval flow contract. Still open. pydantic-ai's Tool doesn't have a native "needs approval" concept. Options:

    • (a) Expose needs_approval as Tool.metadata["needs_approval"]; caller intercepts.
    • (b) Wrap execute in a HumanApprovalWrapper that raises ApprovalRequired when not approved.
    • (c) Integrate with chinchill-api's tool runner directly (out of scope for this lib).

    Recommend (a): simplest, no behavior change for callers who ignore approval, callers who care can read the metadata. Matches upstream's "needs_approval is just a flag" semantics. Defer (b) / (c) until a concrete consumer asks.

Implementation order

PR 1 first (uncontroversial path setup with deprecation shim). PR 2 is the meat. PR 3 docs to confirm the API shape against a real pydantic-ai integration before merging.

References

Activity

  1. coderabbitai commented on May 29, 2026

    @coderabbitai
    🔗 Related PRs

    #48 - fix: adapter hygiene — Slack stream await, Teams divider, public worker APIs [merged]
    #72 - ci(fidelity): ratchet-down baseline + wire into lint.yml [merged]
    #83 - sync: upstream v4.27.0 (alpha 1) [merged]
    #87 - feat(slack): dynamic bot_token resolver and custom webhook_verifier (vercel/chat#421) [merged]
    #106 - release: 0.4.27 — synced to upstream vercel/chat@4.27.0 [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. patrick-chinchill commented on Jun 21, 2026

    @patrick-chinchill
    CollaboratorAuthor

    Design delivered — the chat/ai subpath port shipped in 0.4.29 (ai/messages + ai/index, mapped in verify_test_fidelity.py).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions