Dev Log
TypeScriptでAI Agentフレームワークを作っている理由
AI agentツールはPythonばかり。でもproductionアプリはTypeScript。このギャップがつらいので、自分たちで作ることにした話。
TL;DR
- AI agentのツールはPython一強だが、productionアプリはTypeScriptで動いている
- この2言語またぎがしんどい。型定義の二重管理、デプロイパイプライン分離、ランタイムをまたいだデバッグ
- RAGを「後付けで組み立てるもの」ではなく、フレームワークのfirst-class primitiveにしたかった
- というわけで
@schift-io/sdkを作っています。Apache 2.0のopen source
そもそもなぜPythonなのか
去年からずっと引っかかっていたことがあります。AIのロジックはPython、アプリケーションのロジックはTypeScript。なぜこの2つが分かれているのか。
歴史的な経緯はわかります。NumPy、PyTorch、Hugging Face。研究スタックがPythonだったので、ツールもPython、チュートリアルもPython。LangChain、CrewAI、AutoGen。全部Python-first。自然な流れです。
でもユーザーが触るアプリケーションは? ほとんどNext.js、Node、React。つまりTypeScript。
「AIツールがある場所」と「productionアプリがある場所」にギャップがあって、みんなmicroservicesやRESTラッパーで無理やりつないでいる。このギャップには見えないコストがかかっている、というのが私たちの実感です。
2言語構成のつらさ
相談に来るチームの構成、だいたいこんな感じです。
- Python
FastAPIでagent/RAGロジックを動かす - Next.jsフロントエンドからHTTPで叩く
- デプロイパイプラインは別々
- 型定義を両方の言語で二重管理
- デバッグが2つのランタイムをまたぐ
誤解のないように言うと、Pythonが悪いわけではないです。ML研究にはPythonが正しい。トレーニングループ、テンソル演算、fine-tuning。これらをTypeScriptに持ってくるべきではない。
ただ、ツールを呼んで、コンテキストを取得して、構造化レスポンスをwebアプリに返すagent。これはアプリケーションロジックです。アプリケーションがある場所で書くのが自然なはず。
2つの言語、2つの型システム、2つのデプロイ先、2セットの依存関係。このスタック税、地味にしんどいです。
既存のツールを見てみる
Mastraは私たちが作っているものに一番近いです。TypeScript-first、Gatsbyチーム出身、GitHub star 22k+、seed $13M。マーケットをvalidateしてくれた存在として尊敬しています。
Vercel AI SDKはNext.jsアプリでLLMレスポンスをstreamingするにはとても良い。40+プロバイダーのモデルルーティングもきれいに動きます。
ただ、RAGに関しては後付け感があります。vector store、embeddingパイプライン、chunkingロジック、全部自分で持ってくる必要がある。データの入口と鮮度管理について、フレームワークとしての意見がない。
ここに私たちのスペースがあると考えました。
RAGを「よしなに」やってくれるフレームワーク
結論から言うと、RAGはフレームワークのfirst-class primitiveであるべきで、3つのサービスをつなぐチュートリアルを読んで自分で組み立てるものではない、というのが私たちの立場です。
Schiftでは、vector storeの設定もembeddingモデルの選択もchunkingの設計も個別にやる必要がありません。agentにbucketを指定すれば、よしなに動きます。
import { Agent, RAG } from '@schift-io/sdk';
const agent = new Agent({ name: 'support-bot', rag: new RAG({ bucket: 'docs' }), model: 'claude-sonnet-4-20250514',});
const response = await agent.run('How do I migrate embeddings?');これで全部です。RAGレイヤーがembedding、retrieval、context assemblyを処理して、agentがtool use、memory、レスポンス生成を担当する。開発者はアプリケーションだけ書けばいい。
ちなみに、retrievalのバックエンドはRustで書いた自前のengineです。p99でsub-300マイクロ秒のvector search。レイテンシが予測可能でself-hostできるものが必要だったんですが、既存の選択肢では足りなかったので自分たちで作りました。
ベンチマーク比較はまだ公開していません。方法論をもう少し詰める必要があるので。ただ、インタラクティブなagentユースケースで効いてくるのはtime-to-first-tokenで、retrievalレイテンシはその大きな部分を占めています。
データ主権という設計制約
enterpriseの開発者から繰り返し聞く話があります。「managed offeringは嬉しいけど、データがどこに行くのか把握したい。」
これ、agentでは特に重要です。社内ドキュメント、サポートチケット、プロダクト仕様にRAGでアクセスするagent。そのデータが自分のコントロール外に出るのは、単発のcompletion requestとはリスクの質が違います。
なので、フレームワークは最初からself-host前提で設計しました。execution pipelineはopen source。フルスタックを自社インフラで動かしたければ動かせます。Terraform configも用意しています。
実際にはほとんどのチームがmanaged cloudを使います。vectorインフラの運用はやりたくないですよね。でも「やろうと思えばできる」が本物であることが、信頼の話を変えるんです。
動かしてみる
最初のテンプレートはカスタマーサポートchatbotにしました。一番よく見る最初のユースケースだし、私たち自身がschift.ioでdogfoodしているからです。
npx create-schift@latest my-agent --template cs-chatbotこれで手に入るもの:
- Schift agentが組み込まれたNext.jsアプリ
- productionと同じ構成のローカル開発環境
schift deployコマンド(アプリのデプロイは開発者側、execution layerは私たちの側)
SDKはnpmの@schift-io/sdk。フレームワークのソースはApache 2.0のopen sourceです。
言っていないこと
Pythonのagentフレームワークがダメだとは言っていません。LangChainもCrewAIも本格的なエコシステムを持っていて、今の時点では私たちよりはるかに大きい。
言いたいのはこういうことです。productionのTypeScriptアプリを作っていてagent機能を足したいとき、そのためだけに2つ目の言語と2つ目のデプロイ先を持ち込まなくていいはず。
それが私たちの解いている問題です。あとは全部そこから派生します。
まとめと今後
フレームワークの完全なドキュメントと追加テンプレートを作っています。CS chatbotの次はlegal-QA agent。すでに複数のチームがSchiftで法律QAを動かしていて、パターンとして固める価値があるからです。
TypeScript agentで何か作っている方、情報交換できると嬉しいです。この領域の難しい問題はLLM呼び出しではありません。それはもう解けている。難しいのはdata ingestionの品質、context assembly、memory。私たちが集中しているのはそこです。
フレームワークを試す: npx create-schift@latest — SDK docsは schift.io/docs