はじめに ドキュメントガイド Keelson は、AI ツールなどで作った社内アプリを、チームで使えるようにするサービスです。アプリをデプロイして動かすだけでなく、利用者にログインを求めたり、アプリを使えるメンバーを指定したりできます。
利用を始めるには、Keelson コンソール でアカウントを作成するか、ログインしてください。
お使いの ChatGPT や Claude Code などでも、Keelson について質問できます。ページ上部の「URL を貼り付けて AI に質問」にある「コピー」ボタンで URL をコピーし、質問と一緒に送ってください。アプリの構成を伝えれば、デプロイできるかどうかや、必要な変更点についても相談できます。
次の例をコピーして試せます。アプリの説明は、ご自身の構成に置き換えてください。
https://keelson.dev/ja/llms.txt
この URL のドキュメントを読み、必要に応じてリンク先も参照してください。
Python と SQLite で作った社内アプリを Keelson にデプロイしたいです。
サンプルで試す サンプルアプリをデプロイし、ログインした人だけが使えることを確認します。所要時間:約 15 分 既存アプリを持ち込む Lovable / Bolt / v0 などで作ったアプリや、手元で開発したアプリをデプロイします トラブルを解決する デプロイに失敗する、利用者がアプリを開けない、保存したデータが消えたときの対処方法を確認します
Python / Node.js / Go の Web アプリ、ビルド済みの静的サイト、決まった時刻や間隔で処理を行う定期実行ジョブに対応しています。社内の数人〜数百人が使う業務アプリを想定しており、利用者数は料金に影響しません。
常時起動や WebSocket を前提とするアプリ、GPU が必要なアプリなどには対応していません。対応するフレームワークや詳しい制約は、対応アプリと制約 を確認してください。
対応条件を満たす既存のアプリも、実行環境に合わせて設定やコードの一部を変更することでデプロイできます。アプリ全体を Keelson 向けに書き直す必要はありません。既存の外部データベースやサービスも引き続き利用できます。必要な準備は、他のツールで作ったアプリを持ち込む を参照してください。
Keelson 以外の環境でアプリを動かす際の注意点は、FAQ にまとめています。
サービス概要と料金は公式サイト にあります。
まず読む
必要になったら参照する
アプリの対応条件やデプロイに必要な設定は、Keelson Deploy Spec にまとめています。AI エージェントに次の URL を渡し、「この仕様とアプリのコードを確認して、Keelson にデプロイするために必要な変更を提案してください」と依頼してください。
https://keelson.dev/ja/docs/reference/deploy-spec.txt
CLI の keelson install-agent コマンドでインストールできる AI エージェント用スキルには、Deploy Spec の内容に加え、Python / Node.js / Go ごとのコードの変更手順が含まれています。
ドキュメントの全文をまとめて AI に渡したい場合は、/ja/llms-full.txt を利用できます。各ページを Markdown で取得するには、URL の末尾の / を .md に置き換えてください(例:/ja/docs/introduction/quickstart/ → /ja/docs/introduction/quickstart.md)。
導入前のよくある質問と回答は、FAQ にまとめています。
クイックスタート サンプルアプリを Keelson にデプロイし、ログインした人だけが使えることを確認します。
所要時間 : 約 15 分。ビルドの待ち時間を含みます。
必要なもの : Keelson のアカウントと、コマンドを実行するターミナル。サンプルアプリ用に外部サービスの API キーを用意する必要はありません。
完了の目安 : ログイン後は挨拶の画面が表示され、ログインしていないシークレットウィンドウではログイン画面が表示されます。
このガイドでは、Claude Code / Codex / Cursor のいずれかを使ってデプロイします。AI エージェントを使わず、CLI から直接デプロイすることもできます。その場合は手順 3 を省き、手順 4 の CLI コマンドを実行してください。
Keelson のアカウントがまだない方は、Keelson コンソール でアカウントを作成してください。
Keelson CLI は、ターミナルからログインやデプロイを行うためのツールです。使っている OS のタブを選び、次のコマンドでインストールしてください。
curl -fsSL https://keelson.dev/install.sh | sh
keelson コマンドが見つからない場合 インストーラーは、コマンドを探す場所(PATH)を変更しません。次の行を ~/.zshrc や ~/.bashrc に追加し、ターミナルを開き直してください。
export PATH = " $HOME /.keelson/bin: $PATH "
Windows 10 / 11 または Windows Server 2016 以降に標準搭載されている Windows PowerShell 5.1 以上で実行します。
irm https: // keelson.dev / install.ps1 | iex
インストール後、現在の PowerShell で keelson コマンドを使えるように、次を実行します。
$ env: Path = " $ env: USERPROFILE \.keelson\bin; $ env: Path "
次回以降の PowerShell でも使えるようにする インストーラーは、コマンドを探す場所(PATH)を変更しません。「環境変数を編集」からユーザー環境変数の Path に %USERPROFILE%\.keelson\bin を追加し、PowerShell を開き直してください。
続けてログインします。ブラウザが開くので、Keelson のアカウントでログインしてください。
サンプルアプリをダウンロード(ZIP) します。
ZIP を展開します。
展開した keelson-hello フォルダを Claude Code / Codex / Cursor で開きます。AI エージェントを使わない場合は、このフォルダでターミナルを開いてください。
サンプルの中身を見る from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
@app.get ( "/" , response_class = HTMLResponse)
def index (request: Request):
email = escape(request.headers.get( "X-Keelson-User-Email" ) or "ゲスト" )
<html lang="ja"><body style="font-family: sans-serif; padding: 2rem">
<h1>こんにちは、 { email } さん</h1>
<p>このアプリは Keelson で動いています。</p>
command : "uvicorn main:app --host 0.0.0.0 --port $PORT"
このアプリは、Keelson が付けるヘッダーからログイン中のユーザーのメールアドレスを読んで表示します。認証のコードは 1 行もありません。
スキルは、AI エージェントが参照する Keelson の設定・デプロイ手順です。Keelson CLI に同梱されています。展開した keelson-hello フォルダでターミナルを開き、使っているエージェントのタブを選んで、次のコマンドを実行してください。
keelson install-agent claude-code --global
--global を付けると、同じユーザーのほかのプロジェクトでも使えるようになります。付けない場合は、現在のプロジェクトにだけインストールします。
keelson install-agent codex
現在のプロジェクトにインストールします。
keelson install-agent cursor
現在のプロジェクトにインストールします。
公開リポジトリからスキルをインストールする場合 インストール方法は、keelson install-agent、Claude Code プラグイン、npx skills add のどれか 1 つだけを使ってください。方法を組み合わせると、同じスキルが 2 つ入ったり、互いに上書きしたりすることがあります。
Claude Code では、マーケットプレイスを追加してからプラグインをインストールします。
/plugin marketplace add keelsonhq/skills
/plugin install keelson@keelson-skills
ほかのエージェントでは、次を実行します。
npx skills add keelsonhq/skills
これらの方法でインストールされるのはスキルだけです。手順 1 の CLI のインストールとログインも必要です。Claude Code プラグインとして入れたスキルは keelson login では自動更新されず、Claude Code のプラグイン更新で追随します。
配置先や更新方法は CLI コマンド を参照してください。
エージェントのチャットに次のように依頼します。
このアプリを Keelson にデプロイして
エージェントがデプロイを開始します。初回の完了には数分かかります。デプロイの開始時には、デプロイ ID と、次のようなアプリの URL が発行されます。
https://<ワークスペース>--hello.keelson.run
AI エージェントを使わない場合は、keelson-hello フォルダで次のコマンドを実行します。
URL はデプロイの完了前にも発行されます。URL が表示された時点では、まだビルドや起動の途中の場合があります。URL を開く前に、次のコマンドで状態を確認してください。<deploy-id> は、デプロイ時に表示された ID に置き換えます。
keelson status <deploy-id>
たとえば ID が d1 なら、keelson status d1 を実行します。status: completed と表示されれば、デプロイの処理は完了しています。続けて手順 5 でアプリが実際に開けることを確認してください。
queued、building_image、starting などの場合は処理中です。少し待ってから、同じコマンドでもう一度確認してください。failed や rolled_back の場合は成功していません。表示された理由と次に必要な操作を確認してください。詳しくはトラブルシューティング を参照してください。
発行された URL をブラウザで開きます。ログイン画面が表示された場合は、Keelson にログインしてください。「こんにちは、… さん」と本文が表示されることを確認します。
Keelson にログインしていないシークレットウィンドウ で同じ URL を開きます。アプリではなく、Keelson のログイン画面が表示されることを確認します。
「ゲスト」と表示される場合も、未ログインという意味ではありません。このサンプルでは、ログイン方法によってメールアドレスを取得できない場合に「ゲスト」と表示します。
これで、ログインした人だけが使えるアプリを専用 URL で開けるようになりました。デプロイしたアプリは Keelson コンソール にも表示されます。
同僚に共有する — 同僚を招待し、相手のアカウントでアプリを開けることを確認します。手順はチームにアプリを共有する を参照してください。
表示を変えて更新する — main.py の文言を変えて、もう一度「デプロイして」と頼みます。更新内容を反映する方法と、以前のバージョンに戻す方法は更新と復元 を参照してください。
自分のアプリをデプロイする — 対応アプリと制約 で対応状況を確認し、持ち込みガイド で準備を進めます。
仕組みを理解する — 基本コンセプト で、ワークスペースやアクセス権、Keelson とアプリの役割分担を確認します。
基本コンセプト Keelson では、社内アプリとメンバーをワークスペースにまとめて管理します。アプリを増やすたびに、ログインやメンバー管理の仕組みを作り直す必要はありません。
このページでは、基本的な用語と、Keelson が用意する機能・アプリ側で実装する機能の違いを説明します。
用語 意味 ワークスペース メンバーやアプリをまとめて管理する単位 アプリ デプロイして利用する業務ツール。案件管理や日報など メンバー ワークスペースに参加している人 グループ 部署やチームなど、アクセス権をまとめて設定するためのメンバーの集まり デプロイ アプリのコードと設定を送り、Keelson 上で使える状態にすること
たとえば、同じワークスペースに「営業日報」と「経費申請」を作り、営業チームには営業日報、全社員には経費申請を共有できます。
Web アプリや静的サイトをデプロイすると、HTTPS で保護された専用 URL が発行されます。証明書の取得や更新は Keelson が行います。
https://<ワークスペース>--<アプリ>.keelson.run
通常のアプリ画面は、URL を知っているだけでは開けません。Keelson がログインとアプリの閲覧権限を確認し、許可されたアクセスだけをアプリに渡します。
Keelson:ログイン・アプリの閲覧権限・IP 制御の条件を確認
アプリ側でログイン画面や Keelson のログインセッションを実装する必要はありません。誰がアクセスしているかは、Keelson が渡すユーザー情報で確認できます。
外部サービスからの Webhook など、ブラウザのログインを使わない呼び出しには別の設定を行います。詳しくは外部システムとの連携 を参照してください。
ユーザーは 1 回ログインすれば、同じワークスペース内で閲覧権限のあるアプリを開けます。Keelson のログインをアプリごとにやり直す必要はありません。アプリが独自の外部認証も使っている場合は、そのログインが別途必要になることがあります。
メンバーとグループはワークスペースで管理し、アプリごとにグループへ権限を割り当てます。
権限 できること 閲覧(view) アプリを開いて利用する 管理(manage) アプリをデプロイし、設定やシークレットを変更する
「閲覧」は、アプリにアクセスして利用するための権限です。アプリ内でデータを登録・編集できるかどうかは、アプリ側の実装で決まります。
新しいアプリには、初期設定で次の権限が割り当てられます。
グループ 含まれるメンバー アプリの権限 everyoneワークスペースの全メンバー 閲覧 developersOwner / Admin / Developer ロールのメンバー 管理(閲覧も含む)
特定のチームだけが利用できるようにする場合は、チームにアプリを共有する を参照してください。
管理権限は、業務上の承認権限とは別です。 「上司だけが申請を承認できる」「担当者だけが案件を編集できる」といったルールは、ユーザーやグループの情報を使ってアプリ側で実装します。
データの保存には、Keelson が管理するアプリ専用のデータベース「Managed SQLite」と、ファイルや画像・動画を保存・取得するためのライブラリ「Files / Media SDK 」を利用できます。これらを含め、Keelson が提供する機能とアプリ側で実装する処理は、次のように分かれます。
機能 Keelson が用意すること アプリで実装すること 画面と業務処理 アプリの URL と実行環境 入力画面、集計、申請などの機能 ログインと権限 ログイン、メンバー管理、アプリを開ける人の確認 本人のデータだけ表示するなど、業務に応じた制御 データの保存 Managed SQLite、Files / Media SDK 保存先に接続し、データを読み書きする処理 API キーなどの秘密情報 シークレットの保管とアプリへの受け渡し 受け取った API キーなどを使って外部サービスに接続する処理 定期実行 設定した時刻・間隔で処理を起動 1 回分の処理を行って終了するコード 運用 ログ、アプリ一覧、Managed SQLite のバックアップと復元 業務上の処理結果やエラーをログに記録すること
通常は、AI エージェントに作りたい機能を伝え、アプリのコードと Keelson の設定を作成してもらいます。
共通の API キーはワークスペースに設定し、アプリへ環境変数として渡せます。アプリごとに別の値を設定して上書きすることもできます。秘密の値をコードや keelson.yaml に直接書く必要はありません。
詳しくは環境変数とシークレット を参照してください。
keelson.yaml に次のように設定すると、アプリ専用の Managed SQLite が用意されます。
接続情報は Keelson が渡します。接続してデータを読み書きするコードは、アプリ側で実装します。
Managed SQLite にはバックアップと復元が付きます。Files / Media のファイルは、このバックアップの対象外です。保存先の選び方はデータベース とファイルとメディア を参照してください。
毎朝の集計や定期的なデータ同期は、keelson.yaml の crons に設定します。Web アプリへのアクセスがなくても実行できます。設定方法は定期実行ジョブ を参照してください。
コンソールでは、各アプリを誰が作ったか、誰が使えるか、最後にいつ利用・デプロイされたかを確認できます。作成者以外も、アプリの管理状況を把握できます。
アクセスがない状態が続くと、Web アプリは停止します。 次のアクセスで起動するため、停止後の最初の応答には通常より時間がかかることがあります。アクセス元に応答を返したあとも続ける処理は、完了まで実行される保証がありません。
アプリが動くサーバー内のファイルは、一時的な保存先です。 再起動や再デプロイで失われるため、残したいデータは Managed SQLite や Files / Media SDK を使って保存してください。
実装時の注意点はアプリが動くタイミング と対応アプリと制約 を参照してください。
FAQ 対応アプリ、料金、アクセス権、データについて、導入前によくある質問をまとめました。設定や操作の詳細は、各回答のリンク先を参照してください。
構成によります。まずは、アプリを作った AI ツールや、アプリのコードを確認できる AI エージェントに、次の文章をコピーして質問するとスムーズです。
https://keelson.dev/ja/llms.txt
この URL のドキュメントを読み、必要に応じてリンク先も参照してください。
このアプリを Keelson にデプロイできるか確認してください。
コードや設定、利用しているデータベース・認証・外部サービスを確認し、
判断に必要な情報が足りなければ、私に質問してください。
ビルド済みの HTML・CSS・JavaScript は静的サイトとして、Next.js などサーバー側の処理があるものは Web アプリとしてデプロイできます。静的サイトは手元でビルドし、外部サービスの接続先なども設定しておきます。
外部から接続できる DB やストレージは使い続けられますが、作成ツール内のデータや認証機能が自動で移るわけではありません。詳しくは持ち込みガイド を参照してください。
はい。移行先の環境に合わせて設定や必要なコードを変更すれば、ローカル環境や別のホスティングサービス、自分のサーバーでも動かせます。
動かす環境に合わせて、Python / Node.js などの実行環境や依存パッケージを用意し、起動設定やデータベースの接続先などを設定します。
Keelson に任せていたログイン・アクセス制御・定期実行が必要な場合は、移行先で用意します。Keelson が渡すログイン中のユーザー情報を使う処理は、移行先の認証方法に合わせて変更します。Files / Media SDK を使う処理も、移行先の保存サービスに合わせたコードの変更やファイルの移行が必要です。
現在は動きません。Streamlit は WebSocket が必須で、Keelson の実行モデルと合わないためです。Gradio は検証中です。対応アプリと制約 を参照してください。
外部 DB(PostgreSQL など)に接続する構成であれば使えます。Managed SQLite(libSQL)には Django ORM 用のバックエンドがないため、Managed SQLite と組み合わせる構成は未対応です。db.mode: none にして接続情報をシークレットで渡し、gunicorn で起動します。フレームワーク別の注意点 を参照してください。
いいえ。Web アプリはアクセスがない状態が続くと停止し、次のアクセスで起動します。そのため、停止後の最初の応答には通常より時間がかかることがあります。
決まった時刻の処理は定期実行ジョブに設定します。アクセス元に応答を返したあとも続ける処理は、完了まで実行される保証がありません。詳しくはアプリが動くタイミング を参照してください。
初めて利用する場合は、14 日間の無料トライアルが終了して、有料契約に移行した日からです。
Starter / Plus :カード登録なしで試せます。トライアル終了までにカードを登録しなければ、料金は発生しません。登録済みの場合は、終了時に有料契約へ移行して初回の請求が発生します。
Team :トライアル開始時にカード登録が必要です。トライアル期間中に解約すれば料金は発生せず、継続する場合は終了時に初回の請求が発生します。
有料契約に移行せずトライアルが終了すると、新しいデプロイ・アプリの起動・定期実行ができなくなります。データの扱いは、このページのトライアル終了・解約後の説明 を参照してください。
トライアルを使い切ったアカウントで別のワークスペースを作る場合は、決済完了時に課金が始まります。詳しくは料金と契約の運用 を参照してください。
Plus 以上です。Developers は、アプリを開発・管理するメンバーの人数枠です。開発・管理する人が 2 人なら、2 人分の枠が必要です。アプリを利用する 50 人は App User として追加でき、その人数は料金に影響しません。
Developers の人数枠には、Owner / Admin / Developer ロールのメンバーを数えます。あわせて「同時に使えるアプリ数」(Starter 1、Plus 2、Team 4)が用途に合うかを確認してください。詳しくはプランと制限 を参照してください。
有料契約中は、ワークスペースに保持できるアプリ数に上限はありません。アプリ数について制限されるのは、「同時に使えるアプリ数」です。
直近 5 分にアクセスがあったアプリが、同時利用の枠を使います。アクセスがなくなったアプリは停止状態(スリープ)になり、枠が空きます。
トライアル中は、ワークスペースに保持できるアプリ数にも 3 個の上限があります。ただし、静的サイトとしてデプロイ済みのアプリは、この 3 個に数えません。詳しくはプランと制限 を参照してください。
同時に使えるアプリ数の上限に達していると、停止中のアプリを開いた利用者には、起動できる枠が空くまで待つよう案内する画面が表示されます。枠を使っているアプリへのアクセスが約 5 分途絶えると、その枠が空きます。他のアプリが使われ続けている間は空きません。重要なアプリには優先起動 (有料契約中は Plus 以上、トライアル中は全プラン)で枠を予約できます。
含まれません。外部 API の利用料は、その API の提供元との契約に基づいて別途発生します。API キーはシークレットとして設定し、アプリから利用します。詳しくは外部システムとの連携 を参照してください。
開けません。ワークスペースのメンバーがログインし、そのアプリの閲覧権限を持っている場合だけ表示されます。ログインしていない人にはログイン画面が出ます。社外の人に見せるには、その人をメンバーとして招待します(App User は人数無制限)。詳しくは認証とログイン を参照してください。
アプリとその Managed SQLite は、アプリ作成時に選んだリージョンに配置されます。既定は日本です。
※ 現在選べる配置先は日本のみです。米国西海岸は準備中で、提供開始前に指定すると作成が拒否されます。
Managed SQLite には、全プランでバックアップと復元が付きます。Files / Media SDK のファイルや外部 DB は、このバックアップの対象外です。
日次バックアップ、手動バックアップ、指定した時点のデータに戻す機能(PITR)、ダウンロードが使えます。詳しくはデータベース を参照してください。
Managed SQLite、Files SDK 、Media SDK に保存したデータは、通常の再デプロイだけでは消えません。一方、アプリが動くサーバー内のローカルファイルは、再起動・再デプロイで失われます。
DB の変更処理やアプリのコードでデータを削除・更新した場合は、その変更が反映されます。保存先の違いはデータベース 、変更を戻す方法は更新と復元 を参照してください。
有料契約に移行せずトライアルが終了した場合や、解約して契約期間が終了した場合は、新しいデプロイ・アプリの起動・定期実行ができなくなります。アプリとデータがその場で削除されることはありません。
削除対象のアプリには、Owner / Admin 向けにコンソールとメールで削除が予告されます。猶予期間は、削除予告が記録された時点から、一度も支払いがないワークスペースでは 3 日、支払い実績があるワークスペースでは 30 日です。具体的な削除予定日は予告で確認してください。
猶予期間内に有料契約を開始・再開すれば、削除予告は取り消され、アプリとデータを保持できます。再契約せず猶予期間を過ぎると、対象のアプリは自動削除されます。削除後は、データベースのバックアップや Files のファイルなどが通常の利用から切り離された状態で 7 日間保管されますが、復元は保証されません。
Managed SQLite のバックアップは猶予期間中もダウンロードできます。Files / Media のファイルは契約終了までに取り出してください。詳しくは料金と契約の運用 を参照してください。
有料契約中のダウングレードは、現在の請求期間の終わりに適用されます。それまでは現在のプランを利用できます。トライアル中のプラン変更は、直ちに適用されます。
プラン変更だけでアプリやデータが削除されることはありません。ただし、変更先のプランの上限を超えている場合は、利用に制限がかかります。たとえば、同時に使えるアプリ数が上限に達している間は、停止中のアプリを新たに起動できません。Developers の人数枠を超えている間は、開発・管理するメンバーを追加できません。
ほかの上限を超えた場合の扱いは、料金と契約の運用 を参照してください。
アプリを作る 対応アプリと制約 Keelson は、Python・Node.js・Go の Web アプリ、静的サイト、定期実行ジョブに対応しています。
フレームワークやデータの保存方法によっては、コードや設定の変更が必要です。以下の表で対応状況を確認してください。
Dockerfile は不要です。アプリに含まれていても、Keelson のビルドには使用されません。
アプリ 対応状況 補足 Python の Web アプリ(FastAPI、Flask など) 対応 環境変数 PORT で指定されたポートで起動。Flask は gunicorn を使用 Node.js の Web アプリ(Express、Hono、Next.js など) 対応 環境変数 PORT で指定されたポートで起動。Next.js は next start Go の Web アプリ(net/http、Gin など) 対応 Keelson がビルドして ./app で起動 ビルド済みの静的サイト / SPA(React、Vue、Svelte など) 対応 assets にビルド出力を指定静的な画面 + API サーバー(ハイブリッド構成) 対応 assets.api で API のパスを指定定期実行ジョブのみ 対応 共通の必須項目に加えて crons を設定し、Web サーバー用の command は省略 外部の PostgreSQL / MySQL / libSQL に接続する 対応 db.mode: none。接続情報はシークレットで渡す外部 API(OpenAI、Slack、Google Sheets など)を呼ぶ 対応 外部通信は制限なし(SMTP ポート TCP 25・465・587・2525 のみ常に遮断) ファイル SQLite に永続データを保存している(sqlite3、better-sqlite3 など) 変更が必要 接続部分を libSQL クライアントに置き換えて db.mode: libsql。SQL は通常そのまま(Managed SQLite は SQLite 互換)だが、クライアント API の差(Node.js は非同期化、Python は row_factory 等)に応じた修正が要る。Python / Node.js のローカル開発は file:local.db で従来どおり ローカルファイルに残しておきたいデータを保存している 変更が必要 Managed SQLite か Files SDK / Media SDK へ。実行中に保存したローカルデータは再起動後に引き継がれない アプリ内でタイマーやバックグラウンドスレッドを動かしている 変更が必要 時刻で動く処理は定期実行ジョブに移し、リクエストの後に続く処理はバックグラウンドタスク に投入する(アプリが動くタイミング ) Django 外部 DB 接続のみ対応 db.mode: none で PostgreSQL などの外部 DB に接続し、gunicorn で起動する。Managed SQLite(libSQL)には Django ORM 用のバックエンドがないため、Managed SQLite との組み合わせは未対応(フレームワーク別の注意点 )Streamlit 未対応 WebSocket が必須のため、現在は動きません(フレームワーク別の注意点 ) Gradio 検証中 4 以上を検証中。現時点では動作を保証しません Ruby / PHP / Java / Rust / .NET / Elixir 未対応 対応ランタイムは Python / Node.js / Go のみ Dockerfile で apt パッケージを追加している 未対応 root 権限なし。画像・動画系は -media ランタイムで代替できる場合あり 常駐プロセス・デーモン・WebSocket サーバー前提 未対応 アイドル時に停止する実行モデルと合わない Redis / Kafka / DB サーバーを自前で起動する 未対応 外部サービスとして接続するのは可 GPU が必要 未対応
「変更が必要」のアプリは、コードや設定を変更して対応できる場合があります。AI エージェントに確認を依頼すると、必要な変更を提案します。
再生成できる一時データは、ローカルファイルに保存できます。一時的な SQLite の利用には db.local_sqlite の宣言が必要です。条件は keelson.yaml リファレンス を参照してください。
他のツールで作ったアプリ(Lovable、Bolt、v0 など)をデプロイする手順は持ち込みガイド にあります。
keelson.yaml の runtime で選びます。迷ったら -slim から始め、画像・動画・PDF 処理のライブラリ(Pillow、sharp、ffmpeg など)が必要になったら -media に切り替えます。
ランタイム 言語バージョン ビルド時の処理 python-slim / python-mediaPython 3.12 requirements.txt または pyproject.toml から自動インストールnode-slim / node-mediaNode.js 24 package.json と package-lock.json から依存を自動インストール。npm run build があれば実行go-slim / go-mediaGo 1.26 go.mod から go build し、./app として起動
Go のバージョンは、ビルドに使用するツールチェーンのバージョンです。表のビルド処理は、サーバー側の処理があるアプリや定期実行ジョブが対象です。依存パッケージはビルド時にインストールされます。command には起動コマンドだけを書きます。
Node.js: Keelson 上でのビルドには npm を使います。pnpm-lock.yaml / yarn.lock のみの構成は対応していないため、package-lock.json を用意してください。静的サイトは、手元で pnpm や Yarn を使ってビルドしたものも配信できます。
Go: CGO_ENABLED=0 でビルドします。cgo に依存するライブラリは使用できません。
依存ファイルの要件やビルドの制約は、keelson.yaml リファレンス を参照してください。
項目 内容 OS / CPU Linux / x86_64 権限・システムパッケージ 非 root で動作します。sudo や apt-get は使えません Web サーバーの起動 0.0.0.0 と環境変数 PORT で指定されたポートで待ち受けますデータの保存 ローカルファイルは永続保存されません。残したいデータには Managed SQLite や Files / Media SDK を使います 処理の実行 リクエスト処理、バックグラウンドタスク、定期実行ジョブに対応します。詳しくはアプリが動くタイミング を参照してください
実行時間やアプリ数などの上限はプランと制限 を参照してください。
Python(FastAPI)の例です。keelson.yaml と requirements.txt と app.py の 3 ファイルでデプロイできます。
from fastapi import FastAPI
return { "message" : "Hello from Keelson" }
if __name__ == "__main__" :
uvicorn.run(app, host = "0.0.0.0" , port = int (os.environ[ "PORT" ]))
通常は AI エージェントが keelson.yaml を書くので、自分で作る必要はありません。
アプリが動くタイミング このページでは、サーバー側の処理があるアプリの実行方法を説明します。静的サイトの配信には、アプリサーバーの起動は必要ありません。静的な画面と API サーバーを組み合わせるハイブリッド構成では、以下の起動・停止の説明は API サーバーに当てはまります。
Keelson は、アクセスに応じてアプリサーバーを起動し、アクセスがない状態が続くと停止します。次のアクセスがあると、再び起動します。
画面表示や API の処理はリクエストを受けて実行し、リクエストの後に続ける処理はバックグラウンドタスクに投入し、毎日の集計などは Keelson の定期実行ジョブで実行します。アプリが常に起動していることを前提にした処理には対応していません。
アプリが停止しているときにリクエストを受けると、Keelson がアプリを起動します。このため、停止後の最初のアクセスでは、通常より応答に時間がかかることがあります。
再起動すると、メモリ上の変数や、アプリの実行中にローカルファイルへ保存したデータは引き継がれません。残しておきたいデータは、Managed SQLite や Files / Media SDK に保存してください。
詳しくはデータベース(Managed SQLite) とファイルとメディア を参照してください。
データの保存や外部 API の呼び出しなど、そのリクエストで必要な処理は、レスポンスを返すまでに完了させてください。
レスポンスを返した後にバックグラウンドで続ける処理は、最後まで実行されることが保証されません。FastAPI の BackgroundTasks や、完了を待たずに開始する非同期処理を使う場合は、処理方法の変更が必要です。短い処理はレスポンスを返す前に await で完了させ、レスポンスの後も続ける必要がある処理はバックグラウンドタスク に投入します。
AI の回答生成など、結果を少しずつ返す処理にはストリーミングを利用できます。ただし、接続が切れた後も処理を続ける仕組みとしては利用できません。
外部 API の重い呼び出し、PDF や画像の生成、リクエストの時間上限を超える処理などは、keelson.yaml の tasks に宣言し、アプリから SDK で投入します。Keelson は Web アプリとは別の実行環境でタスクのコマンドを 1 回起動し、失敗したときは自動で再試行します。
同じタスクが 2 回以上実行されることがあるため、2 回実行されても壊れないように書いてください。設定方法はバックグラウンドタスク を参照してください。
毎朝のレポート作成や定期的なデータ同期は、keelson.yaml の crons に設定します。Web アプリにアクセスがなくても、設定したスケジュールに従って実行されます。
ジョブは Web アプリとは別の実行環境で起動し、指定したコマンドの処理が終わると終了します。Web アプリと共有するデータは、データベースなどに保存してください。
アプリ内のタイマーやスケジューラで時刻を待つ方法は、アプリの停止中には動作しません。定期的な処理は Keelson の定期実行ジョブに設定してください。
設定方法は定期実行ジョブ を参照してください。
やりたいこと 実装方法 フォームの内容を保存する リクエスト処理中に保存し、結果を返す AI の回答を順次表示する リクエスト処理中にストリーミングで返す 毎朝レポートを作成する 定期実行ジョブに設定する 外部サービスと定期的に同期する 1 回分の同期処理を定期実行ジョブで実行する 重い処理を受け付けて、レスポンスの後に実行する バックグラウンドタスクに投入する 受け付けた処理を後でまとめて実行する(待ち時間を許す) 未処理の内容を DB に保存し、定期実行ジョブで処理する
DB に保存して後で処理する方法では、次のジョブ実行まで待ち時間が発生します。すぐに開始したい処理にはバックグラウンドタスクを使ってください。どちらの方法でも、処理の重複や失敗に備える必要があります。詳しくはバックグラウンドタスク と定期実行ジョブの設計 を参照してください。
Keelson は常駐ワーカーを提供していません。リクエストの後に続ける処理は、バックグラウンドタスクに投入してください。
ここまでの説明は、サーバー側の処理が対象です。ブラウザ側のタイマーや画面の自動更新に、この制約は適用されません。
HTTP リクエスト、バックグラウンドタスク、定期実行ジョブには、それぞれ実行時間の上限があります。長い処理は、上限内に完了する単位に分けてください。
詳細はプランと制限 、バックグラウンドタスク 、定期実行ジョブ を参照してください。
他のツールで作ったアプリを持ち込む Lovable、Bolt、v0 などで作ったアプリや、手元で開発したアプリも、ソースコードを用意して Keelson に持ち込めます。対応状況とデプロイに必要な変更は、アプリの言語や構成、データの保存方法によって異なります。
まず AI エージェントにコードを確認してもらい、必要な変更を確認してからデプロイします。外部サービスにあるデータや利用者のアカウントは、コードをデプロイしただけでは Keelson に移りません。
アプリの作成に使ったツールからコードをエクスポートするか、Git リポジトリを手元に取得し、アプリのフォルダを AI エージェントで開きます。
Keelson CLI とエージェント用スキルのインストール、Keelson へのログインがまだの場合は、クイックスタート の手順 1 と 3 を参照してください。プロジェクト単位でスキルをインストールする場合は、サンプルアプリではなく、持ち込むアプリのフォルダで実行します。
次のように依頼してください。
このアプリを Keelson にデプロイしたいです。https://keelson.dev/ja/llms.txt を入口に、リンク先の対応アプリ・制約と Keelson Deploy Spec を読んでください。そのうえでコードを確認し、デプロイできるかと必要な変更を説明してください。データベース、ログイン、ファイルの保存先、定期的な処理を確認し、既存のデータや利用者のアクセス権に影響する変更は、実施前に説明してください。
エージェントが確認するのは、主に次の点です。
確認すること 確認する理由 アプリの言語とフレームワーク Keelson の対応範囲と、起動・ビルド方法を確認するため データの保存先 外部 DB を使い続けるか、Managed SQLite に変更するかを判断するため ログインとアクセス権 既存の利用者が自分のデータを引き続き使えるようにするため ファイルの保存先 再起動で消える保存方法になっていないかを確認するため タイマーやバックグラウンド処理 時刻で動く処理は定期実行ジョブ、リクエストの後に続く処理はバックグラウンドタスク のどちらに移すかを決めるため
対応している言語・フレームワークは対応アプリと制約 、処理の実行方法はアプリが動くタイミング にまとめています。
アプリから接続できる外部サービスは、デプロイ後も使い続けられます。この場合、データを移す必要はありません。たとえば、外部 DB を使うアプリは db.mode: none にし、接続情報を設定します。
サーバー側で使う API キーやパスワードはシークレット で渡します。ブラウザ側で使うサービスの URL や公開用のキーは、そのサービスの案内に従って設定してください。秘密の値をブラウザに送るコードへ埋め込まないでください。
Supabase などをブラウザから直接呼ぶ構成では、外部サービス側のアクセス権設定も引き続き必要です。Keelson のログインでアプリを保護しても、外部サービスのデータ権限が自動で置き換わるわけではありません。
Keelson では、アプリを開くときに Keelson のログインが必要です。元のログイン機能を残すと、利用者は両方にログインすることになります。
元のログインを外せるかどうかは、ユーザーの識別やデータのアクセス権に使っているかで判断します。
元のログインの役割 対応方法 アプリを開く人を制限するためだけに使っている Keelson のログインとアプリのアクセス権に置き換えることを検討できます ユーザーごとに見せるデータを制限している 元の認証を残すか、Keelson のユーザー情報を使って権限を判定するように変更します データに元のサービスのユーザー ID を保存している 既存のユーザーと Keelson のユーザーをどう対応付けるかを決めます
たとえば Supabase の RLS(行ごとのアクセス制御)で auth.uid() を使っている場合、ログイン機能だけを外すと、誰のデータかを判定できなくなります。ログイン画面を削除する前に、データへのアクセス方法を確認してください。
アプリの実行中にローカルファイルへ保存したデータは、再起動・再デプロイ後に引き継がれません。残したいものに合わせて保存方法を変更します。
保存先を変更する場合は、コードの変更に加えて、既存データを移す手順もエージェントに確認してください。
デプロイ前に、Keelson CLI とエージェント用スキルのインストール、Keelson へのログインを済ませてください。まだの場合は、クイックスタート の手順 1 と 3 を参照してください。
変更内容を確認したら、エージェントに依頼します。
確認した内容で必要な変更と keelson.yaml の作成を行い、このアプリを Keelson にデプロイしてください。
エージェントはアプリの構成に合わせて設定を作成します。主な構成は次のとおりです。設定を自分で書く必要はありません。
アプリの構成 デプロイ方法 静的サイト / SPA(ビルド済みの HTML・CSS・JavaScript) ビルドしたファイルを assets に指定して配信します。外部サービスの API をブラウザから呼ぶアプリも含みます サーバー側の処理がある Web アプリ(Next.js、Express、FastAPI など) command で Web サーバーを起動します静的な画面と API サーバーを組み合わせたアプリ assets と command を設定し、assets.api で API のパスを指定します(ハイブリッド構成)
設定の読み方は keelson.yaml の設定 、操作手順はデプロイする を参照してください。
静的サイトは、手元でビルドしてからデプロイします。Keelson にアップロードされるのは assets.dir の中身と keelson.yaml で、Keelson 上で npm install や npm run build は実行されません。
ハイブリッド構成でも、画面のファイルは手元でビルドし、assets.dir に用意してからデプロイします。サーバー側のビルドは Keelson が行いますが、assets として配信するのはアップロードしたファイルです。
ビルド時に読み込むサービスの URL や公開用のキーは、ビルド前に設定します。デプロイ後にサーバーの環境変数を設定しても、ビルド済みの画面には反映されません。エージェントには、設定を含めてビルドとデプロイを依頼してください。
Keelson の URL で画面が開き、必要な操作ができる
既存のデータが表示され、追加・更新したデータも保存される
画像や添付ファイルを表示・閲覧できる
元の認証を残した場合も含め、想定したログイン手順で利用できる
他のメンバーも利用でき、見せるべきでないデータは表示されない
作成ツールが提供するデータベース、認証、ファイル保存、サーバー側の関数は、ソースコードだけをデプロイしても移りません。外部から利用できるものは接続を維持し、利用できないものはデータの移行や処理の書き換えが必要です。
作成ツール内の編集機能も Keelson には移りません。デプロイ後のコード変更は、手元の AI エージェントなどで行い、再デプロイして反映します。
keelson.yaml の設定 keelson.yaml は、アプリの起動方法やデータベースの利用、定期実行などを Keelson に伝える設定ファイルです。デプロイするアプリのルートフォルダ(プロジェクトルート)に置きます。
通常は、デプロイを依頼した AI エージェントが作成・更新します。 このページでは、エージェントが作った設定を確認するときに役立つ項目を説明します。すべての設定項目や細かい条件は keelson.yaml リファレンス を参照してください。
Python の Web アプリで、Keelson のデータベースを使う例です。
runtime : python-slim # Python の実行環境
command : "python app.py" # Web サーバーを起動するコマンド
mode : libsql # Keelson の Managed SQLite を使う
項目 確認すること slugアプリを識別する名前です。https://<ワークスペース>--<slug>.keelson.run の一部になります runtimeアプリの言語に合う実行環境です。Python / Node.js / Go から選びます commandアプリの Web サーバーを起動するコマンドです。依存パッケージのインストールはビルド時に行われます db.modeKeelson のデータベースを使うなら libsql、使わない場合や外部 DB を使う場合は none です
db.mode: libsql はデータベースを用意する設定です。アプリのコードにも、用意された DB に接続して読み書きする処理が必要です。既存のファイル SQLite が、この設定だけで Managed SQLite に切り替わるわけではありません。
Files / Media SDK だけを使うアプリは db.mode: none で構いません。Files / Media の利用を宣言する設定は不要です。
どのアプリにも slug、runtime、db.mode が必要です。そのほかの項目は、アプリの構成で変わります。
アプリの構成 主な設定 Web アプリ command に起動コマンドを書く静的サイト / SPA type: web と assets を設定し、command は書かない静的な画面 + API サーバー(ハイブリッド) assets と command の両方を設定する定期実行だけのアプリ crons を設定し、Web サーバー用の command は書かない
サーバー側の処理がある Web アプリには、crons を追加できます。その場合、type: web は指定しません。type: web と crons は併用できません。定期実行の設定は定期実行ジョブ を参照してください。
ビルド済みのファイルを配信する例です。assets.dir にはビルド出力のフォルダを指定します。
fallback : index.html # SPA で、画面の URL を直接開いたときにも index.html を返す
静的サイトは手元でビルドしてからデプロイします。Keelson 上で依存パッケージのインストールやビルドは行われません。通常の静的サイトで、見つからないページを index.html に戻す必要がなければ fallback は省略できます。
/api 以下へのリクエストをサーバーで処理し、それ以外ではビルド済みの画面を配信する例です。
この構成でも、画面のファイルは手元でビルドし、assets.dir に用意してからデプロイします。サーバー側のビルドは Keelson が行いますが、assets として配信するのはアップロードしたファイルです。
command : "node server.js"
アプリ名と保存先が意図どおりか。 slug が対象アプリの名前か、db.mode が利用するデータベースに合っているかを確認します。
API キーやパスワードが直接書かれていないか。 secrets には名前と説明だけを書き、値はコンソールなどから設定します。
必要な定期処理が設定されているか。 アプリ内のタイマーに任せず、crons のスケジュールを確認します。
起動コマンドや依存ファイルの確認は、エージェントに依頼できます。次のコマンドでは、アップロードせずに設定と送信対象のファイルを確認できます。
keelson deploy --check --json
この確認だけでは、実際にアプリが起動するかやプランの上限内かまでは分かりません。デプロイ後はアプリの URL を開き、動作を確認してください。
keelson.yaml の変更は、次のデプロイで反映されます。エージェントに「設定を変更して再デプロイしてください」と依頼してください。
PORT などの環境変数は Keelson が設定します。古い設定を引き継ぐ場合は、廃止された項目を削除・置換してください。必要な変更や検証エラーの確認には、keelson.yaml リファレンス を参照してください。
Keelson SDK Keelson SDK は、アプリのコードから Keelson のファイル保存・ユーザー情報・バックグラウンドタスク・メール送信などの機能を使うためのライブラリです。Python・Node.js(JavaScript / TypeScript)・Go 向けに提供しており、必要な機能だけを使えます。
アプリをデプロイするだけなら SDK の導入は不要です。たとえば「アップロードされた画像を残したい」「ログイン中のユーザーに合わせて画面を変えたい」ときに、アプリへ組み込みます。AI エージェントに実装を依頼する場合も、使っている言語と実現したいことを伝え、このページや各機能の解説を渡せます。
機能 できること・用途 使い方 Files SDK アプリ内部で使う非公開ファイルの保存・読み取り・更新・削除・一覧取得。設定 JSON や処理済みデータの記録など ファイルとメディア:Files Media SDK 画像・PDF・添付ファイルの保存と、アプリを閲覧できるメンバー向けの URL 配信。商品写真の表示や申請書の閲覧など ファイルとメディア:Media Identity SDK ログイン中のユーザー情報、所属グループ、ワークスペースのメンバー情報などの取得。作成者の記録やグループに応じた処理の分岐など ログイン中のユーザー情報を使う Tasks SDK keelson.yaml の tasks に宣言したコマンドを、別のインスタンスで実行するよう投入し、状態を確認する。PDF の生成や外部 API の重い呼び出しなど、リクエストの後に続ける処理バックグラウンドタスク Email SDK アプリの利用者へのメール送信と、配信結果(届いた・バウンス・苦情)の受け取り。パスワード再設定や申請の受付通知など 外部システムとの連携:メールを送る
検索や同時更新が必要な顧客・案件などのデータには、データベース(Managed SQLite) を使います。接続には各言語の libSQL クライアントを使い、Keelson SDK とは別に導入します。
アプリの言語に合わせて、依存パッケージを追加します。基本的な機能は3言語で共通ですが、関数名や引数、補助機能は言語によって異なります。
すべての機能を keelson-sdk にまとめています。
コードでは、使う機能を from keelson import files のように読み込みます。files のほか、media、identity、tasks、email を使えます。利用する依存管理ツールに合わせて、requirements.txt や pyproject.toml にも依存関係を記録してください。
機能ごとにパッケージが分かれています。必要なものだけをインストールします。
機能 インストール Files npm install @keelsonhq/filesMedia npm install @keelsonhq/mediaIdentity npm install @keelsonhq/identityTasks npm install @keelsonhq/tasksEmail npm install @keelsonhq/email
コードでは import * as files from "@keelsonhq/files" のように読み込みます。
1つのモジュールに各機能のパッケージをまとめています。
go get github.com/keelsonhq/go-sdk
コードでは github.com/keelsonhq/go-sdk/files のように、使うパッケージを import します。files のほか、media、identity、tasks、email があり、メンバーやグループの一覧取得には directory を使います。
SDK はアプリのサーバー側で使います。ブラウザで動く JavaScript に組み込むものではありません。静的サイト・SPA にはサーバーがないため SDK は使えません。利用したい場合は、SDK を呼ぶ API サーバーを足してハイブリッド構成にします。
接続先や認証情報は、利用する機能に応じて Keelson が環境変数で渡します。通常は SDK が読み取るため、コードにトークンや保存先を書き込む必要はありません。
Files / Media :keelson.yaml への追加設定は不要です。
Identity :ヘッダーから基本的なユーザー情報を読むだけなら追加設定は不要です。所属グループやメンバー情報の取得には、Directory API の有効化と再デプロイ が必要です。
Email :keelson.yaml への追加設定は不要です。差出人は既定で <アプリの slug>@mail.keelson.run です。Team プランでは自社のドメインからも送れます 。
Tasks :投入するタスクを keelson.yaml の tasks に宣言してデプロイします。詳しくはバックグラウンドタスク を参照してください。
Files / Media は、Keelson の接続設定がない手元の環境ではローカルのフォルダに保存します。Identity は、keelson dev serve で起動すると本番と同じユーザー情報のヘッダーを受け取り、利用者を切り替えられます(CLI なしなら KEELSON_LOCAL_MODE=1 でテスト用のユーザー情報を返します)。Tasks は、CLI の keelson dev task run を使って手元でコマンドを同期実行します(手元で動かす )。Email は手元の環境では送信できず、Keelson の接続設定がないため送信時にエラーになります。ローカルで保存したファイルやテスト用のユーザー情報が、デプロイ先へ自動で引き継がれるわけではありません。
Files には言語と OS による制約があります。保存先や制約はファイルとメディアのローカル開発 、ユーザー情報のテスト方法はローカルで動かす を参照してください。SDK が使う設定値は環境変数リファレンス にまとめています。
データベース(Managed SQLite) 顧客情報、案件、申請内容など、アプリで登録・検索・更新するデータの保存先として Managed SQLite を利用できます。Keelson がアプリ専用に用意するデータベースで、保存したデータはアプリを再起動・再デプロイしても残ります。すでに利用している外部 DB に接続することもできます。
画像や設定ファイルにも、再起動後に残せる保存先があります。保存したいものと用途で選びます。
保存したいもの・用途 保存先 顧客情報、案件、申請などを登録・検索・更新する Managed SQLite 設定ファイルや処理済みデータの記録を、アプリ内部で読み書きする Files SDK 画像を画面に表示する、PDF や添付ファイルを利用者が開く Media SDK
たとえば案件管理アプリなら、案件名や担当者は DB に、添付 PDF は Media に保存します。DB には添付ファイルの ID も記録し、案件とファイルを関連付けます。
ファイルの保存方法はファイルとメディア を参照してください。
ここでいう「ローカルファイル」は、Keelson 上でアプリが動くサーバー内に書き込むファイル です。アプリを再起動・再デプロイしたり、アクセスがなくなって停止したりすると、そのファイルは失われます。この性質を「揮発性」と呼びます。
./data.db や /tmp/data.db のように保存先のフォルダを変えても、再起動後にデータを残すことはできません(/data は Keelson が用意せず、アプリからも作成できません)。定期実行ジョブは Web アプリとは別の環境で動くため、これらのファイルを共有することもできません。
アップロードの受け取りや変換途中のファイルなど、処理中だけ使う一時ファイルは /tmp に置いて構いません。後で必要になるデータは、上の表の保存先に保存してください。
Managed SQLite は SQLite 互換の DB なので、SQLite で作ったアプリの SQL やテーブル定義は通常そのまま使えます。変えるのは接続まわりで、sqlite3 や better-sqlite3 でサーバー内のファイルに直接保存している箇所を、libSQL クライアントでの接続に置き換えます。クライアントの API には差があり、Node.js は同期の better-sqlite3 から非同期の @libsql/client になるため await を各ハンドラに足します。Python の libsql は row_factory・型アダプタ・例外クラスが sqlite3 と異なります。Python / Node.js では同じクライアントに file:local.db のようなファイルを渡せば、ローカル開発ではファイル SQLite として動きます。
sqlite3 や better-sqlite3 で残しておきたいデータをファイルに保存している場合は、AI エージェントに次のように依頼できます。
このアプリのデータが、Keelson で再起動・再デプロイした後も残るようにしてください。ファイル SQLite を使っている箇所を確認し、Managed SQLite への変更と、既存データの移し方を説明してください。
デプロイ時の検査でファイル SQLite の利用が検出されると、宣言がなければ拒否されます。再生成できるキャッシュ用途に限り、db.local_sqlite で一時ファイルの利用を宣言できます。この設定でもファイルは再起動後に残りません。詳しくはリファレンス を参照してください。
keelson.yaml に次の設定を書くと、アプリ専用のデータベースが用意されます。通常は AI エージェントが設定と接続コードを作成します。
DB サーバーの準備は不要です。 接続 URL と認証トークンは、Keelson がアプリの環境変数に設定します。
アプリごとにデータを分けます。 接続用の認証情報でアクセスできるのは、そのアプリの DB だけです。
保存を確定したデータは再起動後も残ります。 SQL のコミットが完了した時点で保存されます。
アプリと同じリージョンに配置されます。 現在選べる配置先は日本のみです(region )。米国西海岸は準備中です。
バックアップから戻せます。 日次バックアップ、手動バックアップ、指定時刻への復元に対応しています。
設定ファイルの変更に加えて、アプリ側も libSQL クライアントで DB に接続する必要があります。SQL は SQLite と同じように書けます。Keelson 上では、ローカルのファイルパスではなく、Keelson が渡す接続 URL と認証トークンを使います。Python / Node.js では、環境変数がないときに file:local.db へフォールバックする形にしておくと、ローカル開発では同じコードがファイル SQLite として動きます(Go の libSQL クライアントは file: を開けないため、この形は使えません)。対応クライアントは Python・Node.js・Go で利用できます。
以下はテーブルを作り、データを 1 件保存する例です。Python は libsql、Node.js は @libsql/client を依存パッケージに追加します。
database = os.environ.get( "KEELSON_DB_URL" , "file:local.db" ), # file: = ローカル開発
auth_token = os.environ.get( "KEELSON_DB_AUTH_TOKEN" , "" ),
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
conn.execute( "INSERT INTO items (name) VALUES (?)" , ( "サンプル" ,))
import { createClient } from "@libsql/client" ;
const db = createClient ({
url: process.env. KEELSON_DB_URL ?? "file:local.db" , // file: = ローカル開発
authToken: process.env. KEELSON_DB_AUTH_TOKEN ,
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
await db. execute ({ sql: "INSERT INTO items (name) VALUES (?)" , args: [ "サンプル" ] });
テーブルや列の名前、データ型、制約など、DB の構造を定義したものを「スキーマ」と呼びます。テーブルがまだなければ、上の例のように CREATE TABLE IF NOT EXISTS で作成できます。
デプロイに合わせてテーブルや列を変更する場合は、db.migrate に変更用のコマンドを書きます。この処理を「マイグレーション」と呼びます。
migrate : "python migrate.py"
db.migrate は新しいコードに切り替える前に実行されます。失敗した場合は、それまでのコードでアプリの提供を続けます。ただし、DB に加えた変更は自動では戻りません。
同じコマンドを繰り返し実行しても、テーブルやデータの重複などが起きないようにします(冪等性)。変更後の DB は、それまでのコードでも読み書きできる状態にしてください。command のない静的サイトでは db.migrate は実行されません。詳しくは更新と復元 を参照してください。
SQLite は、同時に書き込みを行う処理を 1 つずつ実行します。Web アプリと定期実行ジョブなどが同時に書き込むと、待ち時間が発生することがあります。書き込みが集中し、応答時間に影響する場合は、処理の見直しや外部の PostgreSQL などを検討してください。
すでに使っている PostgreSQL、MySQL、外部の libSQL などに接続する場合は、db.mode: none にします。接続情報は自分で用意し、シークレットとして設定してください。この設定で Keelson が外部 DB を作成したり、既存のデータを移したりすることはありません。
description : "PostgreSQL の接続文字列"
Django は、この外部 DB 経路でのみデプロイできます(Managed SQLite には Django ORM 用のバックエンドがありません)。詳しくはフレームワーク別の注意点 を参照してください。
外部 DB を使う主なケースです。
ケース 選択肢 データ量や必要な処理速度が Managed SQLite では対応できない 外部 PostgreSQL 同時書き込みが非常に多い PostgreSQL、MySQL BI ツールや基幹システムから直接参照する 共有の PostgreSQL、データウェアハウス Keelson のプランより長い期間のバックアップが必要 外部のマネージド DB
誤ってデータを削除・更新した場合に備えて、すべてのプランでバックアップと復元を利用できます。
方法 用途 日次バックアップ 毎日自動で保存されるバックアップから戻す 手動スナップショット 大きな変更の前など、必要なタイミングでバックアップを作る(1 アプリ 1 日 5 回まで。日付は UTC 基準) 時刻復元(PITR) 戻せる期間内の時刻を指定し、その時点のデータに戻す ダウンロード バックアップや指定時刻のデータを手元に保存する
Starter Plus Team 日次バックアップの保存数 1 回分 3 回分 7 回分 時刻を指定して戻せる期間 過去 24 時間 過去 7 日 過去 14 日
コンソールのアプリ画面で「復元ポイント」を開き、タイムライン上のバックアップや時刻を選ぶと、復元やダウンロードができます。
復元はアプリ単位で、他のアプリには影響しません。復元前の状態は 72 時間保持され、その間は復元を取り消せます。復元の実行には、ブラウザでの承認が必要です。
このバックアップで戻せるのは Managed SQLite のデータだけ です。Files / Media SDK のファイル、外部 DB、アプリのコードや設定は対象外です。
たとえば、DB に保存した添付ファイルの ID を復元しても、Media から削除済みのファイル本体は戻りません。コードや設定を含めた変更の戻し方は更新と復元 を参照してください。
Managed SQLite にはプランごとの固定上限はありません。ただし、基盤側の技術上限は適用されます。また、平常の業務利用を著しく超える負荷や、プラットフォームの安定運用・他のお客様の利用・当社の合理的な運用コストに影響を及ぼす利用を検知した場合、アプリの実行を制限または停止することがあります。緊急時は事前の通知なく制限することがあります
ワークスペースのストレージ(Files / Media SDK のファイル、スナップショット、デプロイ用ファイルなどの合計)はプランごとに上限があります。DB の容量はこれとは別枠です
プラン別の制限はプランと制限 を参照してください。
ファイルとメディア アプリの再起動・再デプロイ後も残したいファイルは、Files SDK または Media SDK で保存します。SDK の概要は Keelson SDK を参照してください。
アプリ内部で読み書きするファイルには Files、画面に表示したり利用者が開いたりするファイルには Media を使います。 Media に保存すると、ブラウザから直接開ける URL を使えるため、画像表示や添付ファイルの閲覧に適しています。
Files SDK Media SDK 主な用途 アプリ内部の処理に使うファイルを保存・更新する 利用者に画像を見せる、PDF や添付ファイルを開いてもらう 例 設定 JSON、処理済み URL の一覧、中間集計ファイル 商品写真、申請書 PDF、利用者向けのレポート 読み取り方 サーバー側のコードが SDK で読み取る。配信用 URL は付かない サーバー側のコードで読み取れるほか、ブラウザから URL で開ける 更新方法 同じ名前(キー)で上書きできる。更新頻度の目安は 1 キーにつき 1 秒に 1 回程度 上書きせず、新しいファイルとして保存するたびに ID が付く 1 ファイルの上限 10 MiB 50 MiB
ファイル形式だけで決める必要はありません。たとえば CSV でも、アプリ内部で集計に使うなら Files、利用者に渡すレポートなら Media が適しています。
Media の URL は誰でも開ける公開 URL ではありません。そのアプリを閲覧できるメンバーだけが、Keelson にログインして開けます。 Files も Media も、利用には keelson.yaml への追加設定は不要です。
Media の閲覧権限はアプリ単位です。「本人の添付ファイルだけを見せる」など、ファイルごとの権限判定は自動では行われません。そのような場合は Files に保存し、アプリ側で権限を確認してからファイルを返す方法を検討してください。
アプリの実行中にローカルファイルへ保存したデータは、再起動・再デプロイ後に引き継がれません。/tmp やアプリディレクトリに書くだけでは、後で使うファイルを残せません。
Files / Media SDK で保存が完了すると、ファイルはアプリの再起動後も残ります。後から同期処理を行う必要はありません。顧客情報や案件など、項目ごとに検索・更新するデータには Managed SQLite を使ってください。
Keelson SDK のインストール方法 に従い、Files または Media をアプリの依存パッケージに追加します。以下のコード例はサーバー側で実行します。通常は AI エージェントに、保存したいファイルと用途を伝えて実装を依頼できます。
Files は、アプリが名前を付けて保存し、必要に応じて同じ名前で更新するファイルに向いています。Web アプリと定期実行ジョブの間で、保存したファイルを共有できます。
保存先の名前を「キー」と呼びます。settings.json や reports/2026-08.csv のように指定します。Node.js / Python の主な操作は、保存する write、読み取る read、削除する delete、キーの一覧を取得する list です。read はファイルがなければ、Node.js では null、Python では None を返します。
次は、設定を保存して読み取り、レポートの一覧取得と削除を行う例です。
import * as files from "@keelsonhq/files" ;
await files. write ( "settings.json" , JSON . stringify ({ theme: "dark" }));
const raw = await files. read ( "settings.json" ); // Uint8Array | null
const settings = raw ? JSON . parse ( new TextDecoder (). decode (raw)) : {};
const keys = await files. list ( "reports/" ); // ["reports/2026-08.csv", ...]
await files. delete ( "reports/2026-07.csv" );
from keelson import files
files.write( "settings.json" , json.dumps({ "theme" : "dark" }))
settings = json.loads(files.read( "settings.json" ) or " {} " ) # read() -> bytes | None
keys = files.list( "reports/" )
files.delete( "reports/2026-07.csv" )
ローカルファイルから移す場合は、書き込みと読み取りの両方を SDK に変更します。Files には配信用 URL がないため、保存したファイルを利用者に渡したい場合は、アプリ側にダウンロード処理を実装するか、Media を使ってください。
複数の処理が同じキーを読み取って更新すると、一方の変更をもう一方が上書きすることがあります。同時更新が必要な処理状況やカウンターなどは、DB のトランザクションで管理してください。
Media は、アプリの画面で見せる画像や、利用者が開く PDF・添付ファイルに向いています。保存したファイルを Keelson が URL で配信するため、アプリ側にファイル配信用の処理を書く必要はありません。
サーバー側のコードで put を呼び、ファイルを保存します。
返されたファイル ID を、案件や商品などのデータと一緒に DB に記録します。
url(id) で URL を取得し、画面の画像やリンクに設定します。ブラウザがその URL にアクセスすると、Keelson が認証を確認してファイルを返します。
画像を保存するサーバー側の関数の例です。引数には、アップロードで受け取った画像データを渡します。
import * as media from "@keelsonhq/media" ;
async function savePhoto ( imageBytes ) {
const id = await media. put (imageBytes, {
contentType: "image/png" ,
// id を DB に記録し、url を画面に返します。
return { id, url: media. url (id) };
from keelson import media
def save_photo (image_bytes):
content_type = "image/png" ,
# file_id を DB に記録し、url を画面に返します。
return { "id" : file_id, "url" : media.url(file_id)}
Keelson 上での URL は /__keelson/media/<ファイルID> という形式です。たとえば、画像の URL を <img> の src に、PDF の URL をリンクの href に設定します。
<!-- 保存したファイルの URL を設定する例 -->
< img src = "/__keelson/media/画像のファイルID" alt = "商品の写真" />
< a href = "/__keelson/media/PDFのファイルID" >申請書を開く</ a >
ファイルの読み取りは Keelson が処理します。URL を知っているだけでは開けず、そのアプリの閲覧権限が必要です。
保存済みのファイルは上書きできません。差し替える場合は新しいファイルを保存し、DB に記録した ID を更新します。不要になった古いファイルは別途削除してください。
サーバー側で中身を読み取るには get(id)、種類(Content-Type)とサイズを調べるには stat(id) を使います。
存在確認は exists(id)、削除は Node.js では del(id)、Python では delete(id) です。
Content-Type を省略すると、ファイル名の拡張子から推測します。推測できない場合は application/octet-stream になります。
手元で開発するときは、Keelson の接続設定がなければ、どちらの SDK もローカルのフォルダにファイルを保存します。手元のファイルが、デプロイ時に Keelson の Files / Media に自動で移されるわけではありません。
Files: ./.keelson/files/ 配下に実ファイルとして書きます。.keelson/ を .gitignore に入れてください
Media: ./media/ 配下に書きます(MEDIA_DIR で変更可)
Keelson 上では、必要な環境変数を Keelson が設定します。
Media のローカルモードでは、URL の既定値は /media/<ファイルID> です。ブラウザで表示を確認するには、開発用サーバーにファイルを返す処理を用意してください。media.url() は URL を返す関数で、ローカルの HTTP 配信を開始するものではありません。
Files SDK と Media SDK のローカルモードは、Node.js / Python / Go のいずれも Linux、macOS、Windows で利用できます。
Files SDK はキーをそのままローカルのファイルパスに対応させます。大文字小文字を区別しない設定の Windows / macOS では、Report と report のように大文字小文字だけが異なるキーを同時には保存できません。パスベースで処理する環境には、チェック後に別のプロセスが symlink や junction を差し替える競合余地があります。信頼できる単一ユーザーのローカル開発用として利用してください。本番の GCS 保存経路にはこの制限はありません。
コンソールや CLI には、アプリのファイルを一覧表示・ダウンロード・差し替える機能はありません。利用者向けのファイル一覧はアプリに用意します。Media は保存した ID から閲覧用リンクを作り、Files は必要に応じてダウンロード処理を実装してください。
上限を超える大容量ファイルは、S3 互換などの外部オブジェクトストレージにアプリから直接保存してください(SMTP ポートを除き、外部通信に制限はありません)
Files / Media のファイルはワークスペースのストレージ容量(プランと制限 )に含まれます。
Managed SQLite のバックアップには、Files / Media のファイル本体は含まれません。DB を復元しても、削除したファイルは戻りません。
定期実行ジョブ 毎朝のレポート作成や、1 時間ごとのデータ同期など、決まった時刻・間隔で処理を動かせます。この処理を「定期実行ジョブ」と呼びます。Web アプリへのアクセスがなくても実行されます。
通常は AI エージェントに、実行したい処理とスケジュールを伝えると、keelson.yaml の crons に設定します。
ワークスペースのタイムゾーンで毎朝 9 時に、前日分の売上を集計する定期実行ジョブを追加してください。実行結果をログで確認できるようにしてください。
Web アプリに、毎日 9 時に report.py を実行するジョブを追加した例です。
description : "前日の売上レポートをメールで送る"
schedule : "0 9 * * *" # 毎日 9:00
command : "python report.py"
timeout : 120 # 1 回の実行を最大 120 秒にする
項目 意味 nameジョブの名前。小文字英数字とハイフンで指定します schedule実行する時刻・間隔を表す cron 式 command1 回分の処理を実行し、終了するコマンド timeout1 回の実行時間の上限(秒)。上限に達すると停止します enabledfalse にすると定期実行を止めます。省略時は true ですdescription任意。ジョブが何をするかの 1 行説明。コンソールの定期実行タブの「説明」列に表示されます。前後の空白は除かれ、空なら未指定と同じです。最大 100 文字。表示専用で、実行内容には影響しません
name、schedule、command は必須です。timeout は 1〜600 秒の範囲で、プランの上限以下を指定してください。省略時は 300 秒ですが、プランの上限がそれより短ければ、その上限が適用されます。上限を超える値を明示すると、デプロイは拒否されます。
Web アプリなしで、定期実行だけのアプリも作れます。その場合はトップレベルの command を省略します。定期実行だけのアプリは「同時に使えるアプリ数」の枠を消費しません。
schedule には、時刻や間隔を 5 つの項目で表す「cron 式」を書きます。
やりたいこと cron 式 毎日 9:00 0 9 * * *平日 9:00 0 9 * * 1-5毎時 0 分 0 * * * *15 分ごと(Plus / Team) */15 * * * *5 分ごと(Team) */5 * * * *毎月 1 日 0:00 0 0 1 * *
スケジュールはワークスペースのタイムゾーン で評価されます。タイムゾーンはワークスペース作成時にブラウザから設定され、後から変更できません。実行開始は予定時刻より遅れることがあります。
最小間隔は Starter 60 分 / Plus 15 分 / Team 5 分です。それより短いスケジュールはデプロイ時に拒否されます。毎分の実行には対応していません。
cron 式の各項目
│ │ │ │ ┌───── 曜日(0–6、0=日曜)
* はすべての値を表します。たとえば 0 9 * * * は「毎月・毎日・すべての曜日の 9 時 0 分」です。
コンソールのアプリ画面で、ジョブごとの実行履歴、成功・失敗、ログを確認できます。「今すぐ実行」で、次の予定時刻を待たずに動作を確認することもできます。
失敗した場合はログを確認し、必要なシークレットや設定値がそろっているか、timeout 内に処理が終わるかを調べます。ログを AI エージェントに渡して、原因の調査と修正を依頼できます。
標準出力と標準エラーのログは、1 回の実行につきそれぞれ 256 KiB まで記録されます。超えた分は省略されます。
実際に開始した実行を数えます。成功・失敗・「今すぐ実行」は含み、スキップされた回は含みません。合計実行時間は、外部 API の待ち時間などを含む経過時間で数えます。platform 起因で実行時間を確定できなかった場合、合計実行時間には数えませんが、実行回数は 1 回消費します。どちらかの月間上限に達すると当月の残りの実行はスキップされます。すでに開始した実行は完了まで継続し、上限は翌月にリセットされます。
最大本数を最短間隔で動かすと、月間上限には収まりません。本数・最短間隔・1 回の実行時間・月間実行回数・合計実行時間は、それぞれ独立した上限です。
プランごとの上限はプランと制限 を参照してください。
定期実行ジョブは、1 回分の処理を行って終了します。アプリを動かし続けるための機能ではありません。
項目 動作 Web アプリとの関係 別の実行環境で動きます。メモリやローカルファイルは共有しません データの保存 実行環境内のファイルは次回に引き継がれません。残したいデータは Managed SQLite や Files / Media SDK に保存します 前回の実行が終わっていない場合 同じジョブの次の実行をスキップします。後で実行するための予約は残りません 実行に失敗した場合 自動ですぐに再試行はしません。次の予定時刻には通常どおり実行します 実行時間の上限に達した場合 処理の途中でも停止します
アプリ内のタイマーやスケジューラは、アプリが停止している間には動作しません。決まった時刻の処理には crons を使ってください。レスポンスを返した後のバックグラウンド処理も、完了が保証されません。リクエスト内で完了させるか、レスポンスの後に続ける処理はバックグラウンドタスク に投入します。
詳しくはアプリが動くタイミング を参照してください。
途中で停止した処理を次回やり直したり、「今すぐ実行」で同じ処理を繰り返したりしても、登録や送信が重複しないようにします。この性質を「冪等性」と呼びます。
たとえば、reports.date に主キーまたは UNIQUE 制約があるテーブルなら、同じ日付のデータがあれば更新できます。
INSERT INTO reports (date, total) VALUES (?, ?)
ON CONFLICT(date) DO UPDATE SET total = excluded.total
受け付けた処理をリクエストの後すぐに実行するなら、まずバックグラウンドタスク を使ってください。タスクを使わずに組む場合や、次の実行までの待ち時間を許せる場合は、次の方法を使います。
Web アプリで受け付けた処理を後でまとめて実行する場合は、未処理の内容を Managed SQLite に保存します。定期実行ジョブが未処理のデータを読み取り、処理してから完了を記録します。
command : "python process_pending.py"
開始までの待ち時間を考慮します。 次のジョブ実行まで待つため、すぐに開始する必要がある用途には適していません。利用者にも待ち時間を案内してください。
同じ処理が繰り返される場合に備えます。 メール送信などが成功しても、完了を DB に記録する前にジョブが止まることがあります。
失敗の回数と理由を記録します。 再試行の上限を設け、繰り返し失敗するデータをどう扱うか決めてください。Keelson が個々の未処理データを自動で再試行・隔離するわけではありません。
リクエスト内で完了できる短い処理は、レスポンスを返す前に済ませてください。
大量のデータを処理するときは、1 回の件数に上限を設け、残りは次回に処理します。実行時間の上限を超える処理は、複数回に分けてください。
外部 API を呼ぶ場合は、相手のサービスが定める呼び出し回数の制限にも合わせます。間隔を広げるか、1 回あたりの呼び出し回数を減らしてください。
sales と reports テーブルが作成済みで、reports.date に主キーまたは UNIQUE 制約がある例です。依存パッケージに libsql を追加します。
この例では、日本時間で前日分を集計します。sales.date には同じタイムゾーンで求めた日付を YYYY-MM-DD 形式で保存している前提です。Asia/Tokyo は集計に使うタイムゾーンに合わせて変更してください。ワークスペースのスケジュール設定が、コードで日付を求める際のタイムゾーンを自動で変更するわけではありません。
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
database = os.environ[ "KEELSON_DB_URL" ],
auth_token = os.environ[ "KEELSON_DB_AUTH_TOKEN" ],
report_date = (datetime.now(ZoneInfo( "Asia/Tokyo" )).date() - timedelta( days = 1 )).isoformat()
"SELECT COUNT(*), COALESCE(SUM(amount), 0) FROM sales WHERE date = ?" , (report_date,)
"INSERT INTO reports (date, count, total) VALUES (?, ?, ?) "
"ON CONFLICT(date) DO UPDATE SET count = excluded.count, total = excluded.total" ,
(report_date, row[ 0 ], row[ 1 ]),
print ( f "集計完了: { report_date } { row[ 0 ] } 件 / { row[ 1 ] } " )
依存パッケージに @libsql/client を追加し、SYNC_API_URL を環境変数に設定します。synced_items テーブルが作成済みで、id に主キーまたは UNIQUE 制約があり、同期先の API が id を持つオブジェクトの配列を返す例です。
import { createClient } from "@libsql/client" ;
const db = createClient ({
url: process.env. KEELSON_DB_URL ,
authToken: process.env. KEELSON_DB_AUTH_TOKEN ,
const res = await fetch (process.env. SYNC_API_URL );
if ( ! res.ok) throw new Error ( `同期先 API のエラー: ${ res . status }` );
const items = await res. json ();
for ( const item of items) {
sql: `INSERT INTO synced_items (id, data) VALUES (?, ?)
ON CONFLICT(id) DO UPDATE SET data = excluded.data` ,
args: [item.id, JSON . stringify (item)],
console. log ( `同期完了: ${ items . length } 件` );
通知処理を notify.py に実装した場合の設定例です。Webhook URL はシークレットで渡します。
- name : SLACK_WEBHOOK_URL
description : "通知先の Slack Incoming Webhook"
- all_of : [ SLACK_WEBHOOK_URL ]
command : "python notify.py"
状況 対処 timeout に 600 秒を超える値、またはプラン上限を超える値を指定した上限以下にし、必要なら処理を分割する スケジュールがプランの最小間隔より短い 間隔を広げる ジョブの本数がプラン上限を超えている 処理をまとめるか、不要なジョブを削除する description が 100 文字を超えている(cron_description_too_long)100 文字以内の 1 行に縮める。自動では切り詰めない type: web と crons を併用している定期実行だけなら type を外す。静的サイトに処理を追加する場合は、サーバーを持つ構成への変更も確認する 廃止された workers: が残っている 削除し、処理に応じて crons かリクエスト処理に変更する
イベント発生後、すぐに開始する必要がある処理。定期実行では次の予定時刻まで待ちます。バックグラウンドタスク を使ってください。
分割できず、1 回の実行時間の上限を超える処理。
ジョブの完了を待って別のジョブを開始するなどの、ワークフロー制御。
バックグラウンドタスク PDF の生成や外部 API の重い呼び出しなど、リクエストを受けた後に時間のかかる処理を、Web アプリとは別のインスタンスで実行できます。この処理を「バックグラウンドタスク」(以下「タスク」)と呼びます。
keelson.yaml の tasks にコマンドを宣言し、アプリのコードから Keelson SDK の enqueue で投入すると、Keelson がそのコマンドを 1 回起動します。失敗した場合は自動で再試行します。
通常は AI エージェントに、リクエストの後に続けたい処理を伝えると、tasks の宣言と投入のコードを書きます。
注文を受け付けたら、領収書の PDF を作ってメールで送る処理をバックグラウンドタスクにしてください。同じタスクが 2 回走っても、PDF とメールが重複しないようにしてください。
処理 使うもの フォームの保存など、リクエスト中に終わる短い処理 リクエスト処理の中で完了させる 毎朝のレポートなど、時刻で動かす処理 定期実行ジョブ (crons)リクエストを受けて、後で走らせる処理 バックグラウンドタスク(tasks)
タスクが向いているのは、次のような処理です。
HTTP リクエストの上限(120 秒)に収まらない処理
外部 API の重い呼び出し(AI の生成・大量のデータ送信など)
PDF・画像の生成、メールの一斉送信
レスポンスを返した後にアプリの中で続ける処理(FastAPI の BackgroundTasks など)は、最後まで実行されることが保証されません。こうした処理はタスクに移します。
keelson.yaml の tasks に、タスクの名前と実行するコマンドを書きます。
description : "注文の請求書 PDF を作る"
command : "python generate_pdf.py"
timeout : 180 # 1 回の試行を最大 180 秒にする(全プランで有効)
max_attempts : 3 # 初回を含めて最大 3 回まで試行する
項目 意味 nameタスクの名前。小文字英数字とハイフンで指定します。投入時にこの名前を指定します command1 回分の処理を実行し、終了するコマンド timeout1 回の試行の制限時間(秒)。省略時は 300 秒(プランの上限がそれより短ければ上限)。上限を超える値を書くとデプロイが拒否されます max_attempts初回を含めた試行の最大回数。省略時は 3 回 description任意。タスクが何をするかの 1 行説明。コンソールのバックグラウンドタスクタブに表示されます。前後の空白は除かれ、空なら未指定と同じです。100 文字を超えるとデプロイが拒否されます(task_description_too_long。切り詰めはしません)。表示専用で、実行内容には影響しません
name と command は必須です。項目の範囲や検証のルールは keelson.yaml リファレンス を参照してください。
アプリのコードから、宣言した名前と入力データを指定して投入します。投入はすぐに返り、タスクの ID(task_id)が返ります。SDK の導入方法は Keelson SDK を参照してください。
from keelson import tasks
task_id = tasks.enqueue( "generate-pdf" , { "order_id" : 1 },
idempotency_key = "order-1-pdf" )
status = tasks.get(task_id)
print (status.status, status.claimed_attempts, status.last_failure_code)
tasks.enqueue( "generate-pdf" , { "order_id" : 2 })
except tasks.TasksError as e:
if e.code == "TASK_MONTHLY_QUOTA_EXCEEDED" :
import { enqueue, get, TasksError } from "@keelsonhq/tasks" ;
const taskId = await enqueue ( "generate-pdf" , { order_id: 1 }, {
idempotencyKey: "order-1-pdf" ,
const status = await get (taskId);
console. log (status.status, status.claimed_attempts, status.last_failure_code);
await enqueue ( "generate-pdf" , { order_id: 2 });
if (e instanceof TasksError && e.code === "TASK_MONTHLY_QUOTA_EXCEEDED" ) {
import " github.com/keelsonhq/go-sdk/tasks "
client, err := tasks. New ()
taskID, err := client. Enqueue (ctx, "generate-pdf" , map [ string ] int { "order_id" : 1 },
tasks. WithIdempotencyKey ( "order-1-pdf" ))
if errors. As (err, & te) && te.Code == "TASK_MONTHLY_QUOTA_EXCEEDED" {
status, err := client. Get (ctx, taskID)
idempotency_key(冪等キー)を渡すと、同じタスク名・同じキーで投入し直しても新しいタスクは作られず、最初のタスクの ID が返ります。キーは 1〜128 文字の英数字・記号です。
get が返す状態(status)は次の 5 つです。
状態 意味 queued未処理。開始待ち・再試行待ちを含みます running実行中 succeeded成功した(終了コード 0) failed失敗した。理由は last_failure_code で分かります(失敗したとき ) cancelled開始前に取り消された
claimed_attempts は開始した試行の数、last_failure_code は最後に失敗した試行の理由です。
完了を画面に出したいときは、タスクのコマンドが結果をデータベースに書き、画面はデータベースの状態列を見る作りにします。get は確認の補助として使います。
タスクのコマンドは、普通のプログラムです。Keelson はコマンドを起動すると、標準入力 に次の JSON を 1 行書いてから閉じます。
{ "attempt_no" : 1 , "payload" :{ "order_id" : 1 }, "schema_version" : 1 , "task_id" : "…" , "task_name" : "generate-pdf" }
キー 内容 attempt_no何回目の試行か(1 から) payload投入時に渡した入力データ(省略時は null) schema_versionこの入力の形式の版。現在は 1 task_idタスクの ID。再試行しても変わりません task_nameタスクの名前
コマンドが終了コード 0 で終われば成功、それ以外は失敗です。
doc = json.loads(sys.stdin.readline())
order_id = doc[ "payload" ][ "order_id" ]
# 例外で終わると終了コードが 0 以外になり、失敗として扱われる
import { readFileSync } from "node:fs" ;
const doc = JSON . parse ( readFileSync ( 0 , "utf8" ));
const orderId = doc.payload.order_id;
// 例外で終わると終了コードが 0 以外になり、失敗として扱われる
AttemptNo int `json:"attempt_no"`
Payload json . RawMessage `json:"payload"`
SchemaVersion int `json:"schema_version"`
TaskID string `json:"task_id"`
TaskName string `json:"task_name"`
if err := json. NewDecoder (os.Stdin). Decode ( & doc); err != nil {
log. Fatal (err) // 終了コード 1 で終わり、失敗として扱われる
タスクは Web アプリとはローカルディスクを共有しません。結果はデータベース か Files / Media SDK に保存してください。コマンドが読める環境変数は定期実行ジョブと同じです。
タスクは少なくとも 1 回 実行されます。失敗した試行は自動で再試行され、成功した後でも終了の連絡が Keelson に届かなければ、もう一度走ることがあります。同じタスクのコマンドが 2 回以上走っても結果が壊れないように(冪等に)書くのは、アプリ側の責任です。
次の 3 つを守ります。
状態を比較して書き換える :「未処理なら処理中にする」を、1 文の UPDATE で行います。更新した行が 0 件なら、別の試行がすでに処理しているので終了します。
UPDATE orders SET pdf_status = 'processing'
WHERE id = ? AND pdf_status = 'pending' ;
外部 API には冪等キーを渡す :決済やメール送信など、同じ依頼を 2 回受けると困る外部 API には、冪等キーを渡します。再試行しても変わらない task_id を使えます。
出力のファイル名や行のキーを固定する :receipts/order-1.pdf のように、入力から決まる名前で保存します。日時や乱数を含む名前にすると、2 回走ったときに出力が 2 つできます。
「注文を保存したら、必ず領収書のタスクも投入する」ようにしたい場合、注文の保存とタスクの投入を 1 つのトランザクションにはできません。注文はアプリのデータベースに、タスクは Keelson 側に記録されるためです。保存の直後にアプリが止まると、注文だけが残ってタスクが投入されません。
これを防ぐには、注文と同じトランザクションで「まだ投入していないタスク」の行(送信待ち行)をアプリのデータベースに書いておき、commit の後に投入します。一般に outbox パターンと呼ばれる方法です。
1 つのトランザクションで、注文の行と送信待ち行(ID・タスク名・入力・投入済みの印)を書く
commit の後、送信待ち行の ID を idempotency_key にして enqueue する
投入に成功したら、送信待ち行に投入済みの印を付ける
投入に失敗した行や、印を付ける前にアプリが止まった行は、次のリクエストか定期実行ジョブで同じキーのまま送り直す。キーが同じなので、二重に投入されることはありません
Web(リクエスト処理) アプリのデータベース Keelson(タスク)
│ ① 注文の行 + 送信待ち行を 1 つのトランザクションで書く
│ ─────────────────────────────▶ │
│ ② enqueue(名前, 入力, idempotency_key = 送信待ち行の ID)
│ ────────────────────────────────────────────────────────────▶ │
│ ◀──────────────────────────────────────────────── task_id ──── │
│ ─────────────────────────────▶ │
④ ②③の前に失敗・停止した行は、次のリクエストか cron が同じキーで送り直す(重複しない)
from keelson import tasks
def place_order (conn, order_id, items):
outbox_id = str (uuid.uuid4())
conn.execute( "INSERT INTO orders (id, items) VALUES (?, ?)" , (order_id, items))
"INSERT INTO task_outbox (id, task_name, payload, enqueued) VALUES (?, ?, ?, 0)" ,
(outbox_id, "send-receipt" , json.dumps({ "order_id" : order_id})),
"SELECT id, task_name, payload FROM task_outbox WHERE enqueued = 0"
for outbox_id, name, payload in rows:
tasks.enqueue(name, json.loads(payload), idempotency_key = outbox_id)
conn.execute( "UPDATE task_outbox SET enqueued = 1 WHERE id = ?" , (outbox_id,))
自動の再試行 :コマンドが走って失敗した場合(exit_nonzero・timed_out・no_completion)、試行回数が max_attempts に達していなければ、10 秒・20 秒・40 秒・80 秒の間隔を空けて再試行します。間隔は指定できません。
コマンドが走る前に終わった場合(delivery_failed・manifest_unresolvable・quota_exhausted)は、再試行せずにそのまま failed になります。
last_failure_code意味 exit_nonzeroコマンドが 0 以外の終了コードで終わった timed_out制限時間(timeout)を超えて打ち切られた no_completion終了の連絡が無いまま期限を過ぎた delivery_failed実行の準備ができてから 1 時間以内に試行を開始できなかった manifest_unresolvable待っている間にデプロイが 2 回以上重なり、試行に使う宣言を解決できなかった quota_exhausted再試行の分、または月をまたいで開始する分の月間枠を確保できなかった
原因を調べる :コンソールのアプリ画面の「バックグラウンドタスク」タブで、タスクの状態と、最後の試行の標準エラー(256 KiB まで。シークレットの値は伏せて表示)を確認できます。標準エラーは SDK の get では返りません。
やり直す :手動の再実行はありません。やり直すには、アプリから投入し直します。冪等キーを付ける場合は、元のタスクとは別のキーにします(同じキーでは元のタスクが返ります)。
取り消されるとき :次の操作をすると、対象の queued のタスクは cancelled になります。実行中の試行は最後まで走りますが、失敗しても再試行しません。
アプリの手動のサスペンド
不正利用によるアプリの隔離
アプリの削除(タスクの記録も消えます)
tasks からその名前を外すデプロイ(外した名前のタスクだけ)
このほか、コンソールの「バックグラウンドタスク」タブから、指定した queued のタスクを 1 件ずつ取り消せます。アクセスが無いことによるアプリのスリープでは、タスクは取り消されません。
項目 上限 宣言数 アプリあたり 10 未処理(queued)のタスク アプリあたり 1,000 件。超えると投入が TASK_BACKLOG_LIMIT_EXCEEDED で拒否されます 1 回の試行の実行時間 既定 300 秒・最大 600 秒。プランごとの上限は Starter 180 秒 / Plus 300 秒 / Team 以上 600 秒 試行回数 既定 3 回・最大 5 回 入力の大きさ 投入要求全体(payload と idempotency_key を JSON にしたもの)で 65,536 bytes。超えると TASK_PAYLOAD_TOO_LARGE 入力の保存期間 タスクが終わってから 7 日で削除 月間枠 定期実行ジョブと合わせた「バックグラウンド実行」の回数と合計実行時間
timeout を省略したときの既定(300 秒)がプランの上限を超える場合は、上限に切り下げます。上限を超える値を明示すると、デプロイは拒否されます。
月間枠では、開始した試行 1 回を 1 回と数え、再試行も 1 回ずつ数えます。上限に達すると、新規の投入は TASK_MONTHLY_QUOTA_EXCEEDED で拒否されます。同じ冪等キーでの投入し直しは、上限に達していても最初のタスクを返します。
プランにより同時に走るタスクの数に上限があり、超えた分は順番を待ちます。月間枠の数値はプランと制限 を参照してください。
タスクは Web アプリのリクエスト処理だけでなく、定期実行ジョブやタスクのコマンドからも投入できます。たとえば、毎晩の定期実行ジョブで対象を探し、1 件ずつタスクに投入できます。
認証は Keelson が自動で行います。コードにトークンを書く必要はありません。
Keelson の外(KEELSON_MODE=local を指定したとき、または Keelson の環境変数が無いとき)では、SDK の enqueue が CLI の keelson dev task run を子プロセスとして起動し、コマンドが終わるまで待ってから返ります(同期実行)。
本番とは次の点が違います。
enqueue が、処理が終わるまで返りません
別のインスタンスではなく、同じ開発機の子プロセスで走ります。本番では見えないローカルのファイルが見えてしまいます
再試行しません。コマンドが失敗しても enqueue はエラーにならず、get が failed を返します
同時実行の制限・未処理件数の上限・月間枠がありません
実行時間はプランで切り下げず、宣言した timeout をそのまま使います
冪等キーで重複を防げるのは、同じプロセスの中で順に投入した場合だけです。同時の投入・別のプロセス・再起動の後は防ぎません
get で引けるのは、同じプロセスの中で投入したタスクだけです
手元で通っても、本番で同じ結果になるとは限りません。本番では再試行やプランの上限がかかり、試行が 2 回以上走ることがあります。
手元で動かすには、keelson dev task run を含む版の CLI が必要です。古い CLI では enqueue が TASKS_LOCAL_CLI_FAILED になるので、keelson upgrade で更新してください。
アプリを通さずにコマンドだけを試すこともできます。
keelson dev task run generate-pdf --payload '{"order_id": 1}'
ログイン中のユーザー情報を使う Keelson がログインと、アプリを開ける人の確認を行います。アプリでは、そのユーザー情報を使って、作成者を記録したり、本人のデータだけを表示したりできます。
「誰がどの申請を承認できるか」など、アプリ内の業務ルールはアプリ側で実装します。用途に応じて、次の 3 つの方法を使い分けます。
やりたいこと 使うもの 追加設定 誰がアクセスしているか知りたい(作成者の記録、自分のデータだけ表示) X-Keelson-User-Id などのユーザー情報ヘッダー不要 アプリの運用者(デプロイ・設定変更ができる人)だけに見せる画面を作りたい ヘッダー X-Keelson-User-App-Perms 不要(権限はコンソールで設定) 部署ごと・役職ごとの分岐、承認者の判定 Identity SDK の attributes.groupskeelson apps directory enable
「上司だけが承認できる」のような業務上の権限は、アプリ管理用の manage ではなく、所属グループ、またはアプリ自身のデータ(担当者テーブルなど)で判断します。manage を持つのはアプリをデプロイ・設定できる人であり、業務上の承認者と一致するとは限りません。
Keelson は、ログイン済みユーザーからのリクエストに、ユーザー情報をヘッダー(リクエストに付く付加情報)として渡します。アプリのサーバー側で読み取れます。
ヘッダー 内容 X-Keelson-User-Idユーザー ID(安定した識別子。DB に保存するならこれ) X-Keelson-User-Emailメールアドレス(Keelson に値がなければ空文字) X-Keelson-User-Name表示名(Keelson に値がなければ空文字)
作成者を記録するなら、データの保存時にユーザー ID も記録します。本人のデータだけを表示するなら、DB の検索条件にその ID を使います。ヘッダーを読み取るだけで、データの絞り込みが自動で行われるわけではありません。
user_id = request.headers.get( "X-Keelson-User-Id" )
email = request.headers.get( "X-Keelson-User-Email" )
const userId = req.headers[ "x-keelson-user-id" ];
const email = req.headers[ "x-keelson-user-email" ];
これらのユーザー情報は、Keelson がログインを確認したうえで付けます。呼び出し元が同名のヘッダーを送っても、Keelson が確認したユーザー情報に置き換えられます。アプリ側で Keelson のログインセッションを管理する必要はありません。
Identity SDK を使うと、ユーザー情報を id、email、name としてまとめて取得できます。導入方法は Keelson SDK のインストール を参照してください。以下の例はサーバー側で実行します。
getCurrentUser はヘッダーを読むだけで、外部への通信や Directory API の有効化は不要です。JavaScript では await を付けて呼びます。ユーザー ID のヘッダーがない場合や空の場合は例外(IdentityError)になります。
import { getCurrentUser } from "@keelsonhq/identity" ;
app. get ( "/" , async ( req , res ) => {
const user = await getCurrentUser ({ headers: req.headers }); // { id, email, name }
res. type ( "text" ). send ( `こんにちは、${ user . name ?? "ゲスト"} さん` );
このアプリでの権限(X-Keelson-User-App-Perms)もまとめて取得するなら getRequestUser(Python は get_request_user、Go は GetRequestUser)を使います。戻り値は getCurrentUser の値に perms を足したものです(使い方 )。
アプリの権限は「閲覧(view)」と「管理(manage)」の 2 種類で、コンソールまたは CLI でグループに割り当てます(グループとアプリ権限 )。manage はデプロイ・設定変更・シークレット編集ができる運用者の権限で、既定では Owner / Admin / Developer が持ちます。Keelson はその結果をヘッダーで渡します。
X-Keelson-User-App-Perms意味 view閲覧できる view,manage閲覧と管理ができる
アプリは manage が含まれるかだけを見ます。グループ名はコードに書きません。
// Express — ヘッダーはリクエストごとに違うので、ハンドラの中で読む
function canManage ( req ) {
const perms = (req.headers[ "x-keelson-user-app-perms" ] ?? "" ). split ( "," );
return perms. includes ( "manage" );
app. get ( "/admin" , ( req , res ) => {
if ( ! canManage (req)) return res. status ( 403 ). end ();
# FastAPI / Flask — 同じくリクエストごとに読む
def can_manage (request) -> bool :
perms = request.headers.get( "X-Keelson-User-App-Perms" , "" ).split( "," )
「経理チームだけが使えるアプリ」は権限の割り当てだけで実現でき、アプリ側のコードは要りません(チームにアプリを共有する )。「運用者だけが設定画面を開ける」は manage の確認で実現できます。誰が manage を持つかは、コードを変えずにコンソールで変えられます。
部署ごと・役職ごとの分岐や、「承認者だけが承認できる」のような業務上の権限が必要なら、Identity SDK でユーザーの所属グループを取得します。
画面の出し分けだけでは不十分です。「本人の申請だけ見える」を実装するときは、一覧の絞り込みに加えて、API で他人の申請 ID を指定しても取得・更新できない ことをサーバー側で確認してください。判定に使うのは、ブラウザから送られた値ではなく、Keelson が付けたヘッダーや SDK の戻り値です。
グループやメンバーの情報を取得するには、Directory API の読み取りを許可し、再デプロイします。有効にしただけでは、実行中のアプリはまだ利用できません。
keelson apps directory enable
再デプロイすると、環境変数 KEELSON_DIRECTORY_TOKEN がアプリに渡され、SDK が自動で使います。トークンはサーバー側だけで使い、ブラウザに渡さないでください。
import { getCurrentIdentity } from "@keelsonhq/identity" ;
const me = await getCurrentIdentity ({ headers: req.headers });
const groups = me.attributes?.groups ?? []; // 例: ["everyone", "developers", "経理"]
const isAccountingMember = groups. includes ( "経理" );
// この結果を使って、経理向けの操作を許可するか判断します。
from keelson import identity
me = identity.get_current_identity( headers = request.headers)
groups = (me.attributes.groups or []) if me.attributes else []
is_accounting_member = "経理" in groups
# この結果を使って、経理向けの操作を許可するか判断します。
attributes.groups に入るのはグループのキー です。
ロールに応じたシステムグループ: Owner は owners developers everyone、Admin は admins developers everyone、Developer は developers everyone、App User は everyone
そのアプリに権限が割り当てられているカスタムグループのうち、ユーザーが属するもの。アプリに割り当てていないグループは出ません
キーは変わらないので、コードに書いて判定に使えます。日本語のキー(経理)も使えます
getCurrentIdentity は Directory API に問い合わせます。戻り値には、ユーザー(user.id、user.email、user.name)、ワークスペースでのロール(workspace.role)、このアプリでの権限(app.permissions)も含まれます。getCurrentUser とはユーザー情報の参照方法が異なります。
担当者の選択肢を出すなど、他のメンバーの情報が必要なときは listMembers / list_members(検索、ロール・グループで絞り込み)、getUser、listGroups が使えます。
メンバーごとに id、email、name、role、image_url が返ります。image_url はプロフィール画像の URL(img.clerk.com から配信)で、画像が無いメンバーは null です。URL に width / height のクエリを付けると、縮小した画像を取得できます。
サーバー側では、選択肢に必要な項目だけを返します。
import { listMembers } from "@keelsonhq/identity" ;
// リクエストを処理する関数の中で取得します。1 回で最大 100 人です。
const page = await listMembers ({ group_key: "developers" , limit: 100 });
const options = page.items. map (( m ) => ({
label: m.name || m.email,
image_url: m.image_url, // 文字列または null
from keelson import identity
page = identity.list_members( group_key = "developers" , limit = 100 )
{ "id" : m.id, "label" : m.name or m.email, "image_url" : m.image_url}
ブラウザ側では、画像が無いときや読み込みに失敗したときに頭文字を表示します。
function avatar ( option ) {
const initials = document. createElement ( "span" );
initials.className = "avatar-initials" ;
initials.textContent = option.label. slice ( 0 , 1 ). toUpperCase ();
if ( ! option.image_url) return initials;
const img = document. createElement ( "img" );
img.className = "avatar" ;
const src = new URL (option.image_url);
src.searchParams. set ( "width" , "64" );
src.searchParams. set ( "height" , "64" );
img.src = src. toString ();
img. addEventListener ( "error" , () => img. replaceWith (initials), { once: true });
アプリの DB には、メンバーの id だけを保存してください (タスクの担当者の列など)。image_url・name・email は保存しません。表示するたびに listMembers や getUser で最新の値を取得します。メンバーが画像を差し替えると、保存した値は古くなります。
手元で動かすときは Keelson のログインがないため、ユーザー情報のヘッダーが付きません。keelson dev serve で起動すると本番と同じヘッダーが付き、閲覧のみの利用者と管理権限のある利用者を切り替えて確かめられます。CLI なしで KEELSON_LOCAL_MODE=1 を付けて起動したときは、Identity SDK が固定の 1 人を返します。手順はローカルで動かす を参照してください。
ローカルではカスタムグループを再現できません。グループごとの分岐は、実際の権限を設定したテスト用アプリでも確認してください。
外部システムからアプリトークンで呼ばれる /api/external/ や /api/webhooks/ へのリクエストには、ログインユーザーの ID は渡されません。getCurrentUser や getCurrentIdentity で利用者を取得する処理とは分けて実装します。認証方法は外部システムとの連携 を参照してください。
ローカルで動かす アプリを手元で動かすと、Keelson のログインがないため、ユーザー情報のヘッダー(X-Keelson-User-Id など)が付きません。keelson dev serve を使うと、Keelson と同じヘッダーを付けたうえで、利用者を切り替えながら動作を確かめられます。
keelson dev serve 経由KEELSON_LOCAL_MODE=1(CLI なし)利用者 名簿の誰にでも切り替えられる 固定の 1 人 ユーザー情報の渡し方 本番と同じヘッダー SDK がテスト用データを返す(ヘッダーは付かない) メンバー一覧・グループ(listMembers など) 名簿から返す(Directory API の有効化は不要) 名簿から返す 必要なもの 最新の Keelson CLI 最新の SDK
通常は keelson dev serve を使います。CLI を入れていない、または古い CLI しかないときは KEELSON_LOCAL_MODE=1 で起動します。どちらでも、アプリのコードは同じです。
-- のあとに、アプリのサーバーを起動するコマンドを書きます。
keelson dev serve -- node server.js
keelson dev serve -- uvicorn main:app --host 127.0.0.1 --port {port}
keelson dev serve -- go run .
CLI がアプリ用の空いているポートを選び、環境変数 PORT で渡します。コマンド中の {port} もその番号に置き換わります。アプリは 127.0.0.1 のそのポートで待ち受けてください
ブラウザでは http://localhost:5173/ を開きます。ポートは --port で変えられます
CLI はアプリの手前に立ち、リクエストごとに選択中の利用者のヘッダー(X-Keelson-User-Id / X-Keelson-User-Email / X-Keelson-User-Name / X-Keelson-User-App-Perms)を付けます。本番と同じく、ブラウザの Cookie と Authorization ヘッダーはアプリへ届きません
起動すると、アプリの URL、現在の利用者、切り替え方が表示されます。Ctrl-C で止めると、アプリのサーバーも止まります
方法 使い方 切り替えページ ブラウザで http://localhost:5173/__keelson/dev を開き、利用者を選びます。開いている別のタブは、再読み込みするまで前の利用者のままです X-Keelson-Dev-As ヘッダーリクエストに X-Keelson-Dev-As: <利用者の ID> を付けると、そのリクエストだけその利用者になります。AI エージェントや curl での確認に使います --askeelson dev serve --as <利用者の ID> -- ... で、起動時の利用者を決めます
curl -H "X-Keelson-Dev-As: local-user-003" http://localhost:5173/api/items
名簿にない ID を指定するとエラーになります。
利用者の一覧(名簿)は JSON ファイルで用意します。次の順で探します。
keelson dev serve: --users <ファイル> → ./.keelson/dev-users.json
KEELSON_LOCAL_MODE=1: 環境変数 KEELSON_LOCAL_USERS_FILE → ./.keelson/dev-users.json
{ "id" : "sample-tanaka" , "email" : "[email protected] " , "name" : "田中 太郎" , "perms" : [ "view" , "manage" ] }, { "id" : "sample-sato" , "email" : "[email protected] " , "name" : "佐藤 花子" , "perms" : [ "view" ] }
項目 内容 id利用者の ID。名簿の中で重複させません。本番の ID とは別の、読みやすい文字列でかまいません email / nameメールアドレスと表示名。空文字も可 perms["view"](閲覧のみ)または ["view", "manage"](管理権限あり)。X-Keelson-User-App-Perms の値になりますimage_url任意。プロフィール画像の URL
名簿の先頭で manage を持つ人が、既定の利用者になります
指定したファイルが無い・形が正しくないときは、起動時にエラーになります
名簿ファイルが無いときは、組み込みの 4 人(local-user-001 から local-user-004)を使います。keelson dev serve では、local-user-003 と local-user-004 は閲覧権限だけです
名簿を変えたら、起動し直してください
アプリのサーバーを、環境変数 KEELSON_LOCAL_MODE=1 を付けて直接起動します。
KEELSON_LOCAL_MODE = 1 node server.js
keelson dev serve --users <ファイル> で独自の名簿を使っているアプリは、直接起動するときも KEELSON_LOCAL_USERS_FILE=<同じファイル> を渡してください。CLI の有無で利用者の ID が変わらなくなります。
Identity SDK はヘッダーを読まず、固定の 1 人(名簿の先頭で manage を持つ人)を今の利用者として返します。名簿ファイルが無いときは、管理権限を持つテスト用ユーザー(local-user-001)になります。利用者は切り替えられません。ヘッダーを直接読むコードには、このテスト用データは適用されません。
getRequestUser は、リクエストのヘッダーから今の利用者と、このアプリでの権限(perms)をまとめて返します。外部への通信はしません。本番と、上の 2 つの動かし方のどれでも同じコードで動きます。
import { getRequestUser } from "@keelsonhq/identity" ;
app. get ( "/admin" , async ( req , res ) => {
const user = await getRequestUser ({ headers: req.headers }); // { id, email, name, perms }
if ( ! user.perms. includes ( "manage" )) return res. status ( 403 ). end ();
res. send ( `${ user . name ?? user . id } さん、こんにちは` );
from keelson import identity
user = identity.get_request_user( headers = request.headers)
if "manage" not in user.perms:
client, err := identity. New ( "" ) // 起動時に 1 回
user, err := client. GetRequestUser (identity. WithHeaders (r.Header))
http. Error (w, "unauthorized" , http.StatusUnauthorized)
canManage := slices. Contains (user.Perms, "manage" )
ユーザー ID のヘッダーが無いときはエラーになります。perms は X-Keelson-User-App-Perms を分けたもので、ヘッダーが無ければ空です。日本語の表示名も正しく読み取れます。
ローカル開発の仕組みは、Keelson にデプロイしたアプリでは動きません。
デプロイ先で KEELSON_LOCAL_MODE が設定されていると、SDK はテスト用データを返さずにエラーにします。KEELSON_LOCAL_MODE を外してください
keelson dev serve も、デプロイ先の環境では起動しません
AI クライアントから使う(MCP)
アプリを MCP サーバー (AI クライアントからアプリを使う機能)にできます。MCP(Model Context Protocol)は、Claude や ChatGPT などの AI クライアント が、外部の「ツール」を一覧して呼び出すための取り決めです。たとえば在庫管理アプリに「品目を検索する」「入荷を記録する」ツールを用意すると、利用者は AI クライアントとの会話の中から、自分の権限の範囲でアプリを操作できます。
アプリ側で用意するのは、keelson.yaml の mcp: でのツールの宣言と、ツールごとの JSON の受け口(ハンドラ)だけです。ログイン、同意画面、AI クライアントとの MCP のやり取りは Keelson が受け持ちます。
アプリ作者が keelson.yaml の mcp: にツールを宣言してデプロイします
利用者が AI クライアントに接続 URL (アプリの URL + /mcp)を登録します
初回は Keelson のログインと同意画面が出ます。利用者が承認すると、AI クライアントがその利用者として接続されます
AI クライアントがツールを呼ぶと、Keelson がメンバーであること・アプリの権限・IP 制限を確かめ、引数を宣言どおりか検査します
Keelson がアプリの POST /api/mcp/<ツール名> を呼び、アプリが返した JSON をツールの結果として AI クライアントに返します
使えるのは、サーバー側のプログラムが動くアプリ(command があり assets がないアプリ)だけです。静的サイト・SPA・ハイブリッド構成では宣言できません。全プランで使え、プランによる違いはありません。
keelson.yaml に mcp: を書いてデプロイします。次の例は、読み取りのツール search_items と、書き込みのツール create_arrival を宣言しています。
instructions : "Look up stock levels and record incoming deliveries."
description : "Search stock by item name."
description : "Record one incoming delivery."
required : [ item_id , quantity ]
キー 意味 enabledtrue でツールを公開します。false にすると宣言を残したまま呼び出しを止めますinstructionsAI クライアントに渡す、ツール全体の説明(省略可) tools[].nameツール名。英小文字で始まり、英小文字・数字・_ だけ。アプリの受け口は POST /api/mcp/<name> になります tools[].descriptionAI クライアントに見せるツールの説明。AI はこれを読んで、いつ呼ぶかを決めます tools[].accessread(読み取り)か write(データを変更する)。読み取りと書き込み・権限 を参照tools[].permissionview(既定)か manage。manage のツールはアプリの管理権限を持つ人だけが使えますtools[].input引数の形(JSON Schema 2020-12)。最上位は type: object
各キーの型・上限・検査の詳細は keelson.yaml リファレンス を参照してください。
mcp.file を使うと、instructions と tools を別の YAML ファイルに置けます。keelson.yaml には enabled と file だけを書きます。
keelson.yaml と同じフォルダの mcp.yaml:
instructions : "Look up stock levels and record incoming deliveries."
description : "Search stock by item name."
description : "Record one incoming delivery."
required : [ item_id , quantity ]
デプロイ時に Keelson CLI が mcp.yaml の中身を keelson.yaml に差し込んでから検査・送信します。手元のファイルは書き換えません
別ファイルに書けるのは instructions と tools だけです。mcp.file と mcp.instructions / mcp.tools は同時に書けません
mcp.file を読めるのは新しい Keelson CLI だけです。古い CLI は「未対応のキー」としてデプロイを拒否します。その場合は keelson upgrade で CLI を最新版にしてください
ツールが呼ばれると、Keelson がアプリに POST /api/mcp/<ツール名> を送ります。パスはツール名で決まり、変更できません。
本文 は、AI クライアントが渡した引数の JSON オブジェクトです(引数がなければ {})。宣言した input で検査済みのものだけが届きます。
ヘッダー は Keelson が組み立てたものだけが届きます。AI クライアントが送ったヘッダーは 1 つも引き継がれないため、AI クライアントのアクセストークンや、偽造された X-Keelson-* ヘッダーはアプリに届きません。
ヘッダー 内容 X-Keelson-User-Id接続した利用者のユーザー ID。本人の識別にはこれを使います X-Keelson-User-Email同じ利用者のメールアドレス X-Keelson-User-Name同じ利用者の表示名 X-Keelson-User-App-Permsその利用者のアプリの権限(view または view,manage) X-Keelson-Auth-Sourcemcp(MCP 経由の呼び出しであることを示す)X-Keelson-Mcp-Tool呼ばれたツール名 X-Keelson-Mcp-ClientAI クライアントの識別子(URL) X-Request-Idリクエスト ID。エラーの結果にも request id: として表示されます
Authorization ヘッダーには Keelson の内部で使う値が入ります。AI クライアントのトークンではないため、アプリでは使いません。ユーザー情報ヘッダーの使い方はログイン中のユーザー情報を使う と同じです。
応答 は 2xx の JSON(1 MiB まで)で返します。JSON オブジェクトを返すと、AI クライアントが項目を読み取りやすくなります。
アプリの応答 AI クライアントに返る結果 2xx と JSON の本文 ツールの結果として本文の JSON を返す 2xx で本文が空・JSON でない・1 MiB を超える エラー(ツールの応答が不正) 4xx エラー。本文の先頭 4 KiB を利用者と AI クライアントにそのまま見せる 3xx・5xx エラー(ツールの実行に失敗)。本文は見せない 60 秒以内に応答がない エラー(実行されたか分からない)
4xx の本文は利用者と AI クライアントに見えます。 見せてよい説明だけを書きます(例:「品目 A-100 が見つかりません」)
1 回の呼び出しは全体で 60 秒 までです。時間がかかる処理はバックグラウンドタスク に投入して、すぐに応答を返します
Keelson は失敗した呼び出しを再試行しません
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
@app.post ( "/api/mcp/search_items" )
async def search_items (request: Request):
user_id = request.headers[ "X-Keelson-User-Id" ]
args = await request.json() # 例: {"query": "ねじ"}
items = find_items( owner = user_id, query = args[ "query" ]) # アプリの検索処理
@app.post ( "/api/mcp/create_arrival" )
async def create_arrival (request: Request):
perms = request.headers.get( "X-Keelson-User-App-Perms" , "" ).split( "," )
if "manage" not in perms:
return JSONResponse({ "error" : "入荷を記録する権限がありません" }, status_code = 403 )
args = await request.json()
if not item_exists(args[ "item_id" ]):
return JSONResponse({ "error" : f "品目 { args[ 'item_id' ] } が見つかりません" }, status_code = 404 )
arrival_id = record_arrival(args[ "item_id" ], args[ "quantity" ])
return { "arrival_id" : arrival_id}
app. post ( "/api/mcp/search_items" , ( req , res ) => {
const userId = req.headers[ "x-keelson-user-id" ];
const items = findItems ({ owner: userId, query: req.body.query }); // アプリの検索処理
app. post ( "/api/mcp/create_arrival" , ( req , res ) => {
const perms = (req.headers[ "x-keelson-user-app-perms" ] ?? "" ). split ( "," );
if ( ! perms. includes ( "manage" )) {
return res. status ( 403 ). json ({ error: "入荷を記録する権限がありません" });
const { item_id , quantity } = req.body;
if ( ! itemExists (item_id)) {
return res. status ( 404 ). json ({ error: `品目 ${ item_id } が見つかりません` });
res. json ({ arrival_id: recordArrival (item_id, quantity) });
permission: manage のツールは、管理権限を持たない人からは Keelson が呼び出しを通しません。上の例のようにアプリ側でも X-Keelson-User-App-Perms を確かめておくと、宣言を変えたときにも安全です。
access: write のツールは、同意画面で「書き込みツール(データを変更できる)」として別に表示されます。 利用者は「読み取りツールだけ承認」を選べます。その場合、書き込みツールは使えません。後から使うには、接続し直して承認します
permission: manage のツールは、アプリの管理権限(manage)を持つ人だけが使えます。 権限の割り当てはメンバーとロール を参照してください
使えないツールは一覧に出ません。 権限が足りないツールと、同意していない書き込みツールは、AI クライアントのツール一覧から除かれます
呼び出しはすべて、接続した利用者本人として、その人の権限の範囲で行われます。メンバーから外れた人やアプリの閲覧権限を失った人の呼び出しは、通常 2 分以内に拒否されるようになります
利用者は、AI クライアントに接続 URL を登録します。接続 URL はアプリの URL の末尾に /mcp を付けたもの(例: https://acme--stock-desk.keelson.run/mcp)で、コンソールのアプリの MCP タブにも表示されます。接続 URL の登録方法は、各 AI クライアントの MCP 設定のドキュメントを参照してください。
AI クライアントに接続 URL を登録します
初回は Keelson のログイン画面が開きます。アプリを使えるアカウントでログインします
同意画面で、AI クライアントに使わせるツールを確認して 承認 を選びます
接続できるのは、そのアプリを閲覧できるメンバーだけです
受け付ける AI クライアントは、claude.ai または chatgpt.com の身元を名乗るものだけです。それ以外のクライアントは、接続 URL を登録してもログインの段階で止まります
アクセストークンの有効期間は 1 時間で、AI クライアントが自動で更新します。更新用のトークンは、60 日使われないか、接続から最長 180 日で切れます。切れたら接続し直します
同じ AI クライアントで同じアプリに接続し直すと、前の接続は解除されます
操作 できる人 効果 ワークスペースの MCP を停止(設定 → セキュリティ → MCP(AI クライアント) ) Owner / Admin ワークスペースのすべてのアプリで呼び出しを止める。接続は残り、許可に戻すとそのまま使える mcp.enabled: false にしてデプロイアプリをデプロイできる人 そのアプリの呼び出しを止める。接続は残り、true に戻してデプロイするとそのまま使える アプリの MCP タブの「接続中の AI クライアント」で 失効 Owner / Admin、アプリの管理権限を持つ人 その接続を解除する。AI クライアントは更新用のトークンも含めて直ちに使えなくなる 「自分の接続中の AI クライアント」で 失効 接続した本人 自分の接続を解除する
停止と mcp.enabled: false は呼び出しを止めるだけです。接続そのものを失効させるのは、解除(失効)だけです。 「自分の接続中の AI クライアント」は、設定 → セキュリティ と同意画面からリンクしています。
mcp.enabled: true のアプリでは、/mcp、/.well-known/oauth-protected-resource、/.well-known/oauth-protected-resource/mcp は Keelson が応答し、アプリには届きません
サーバー側のプログラムが動くアプリ(ハイブリッド構成のサーバー側を含む)では、/api/mcp と /api/mcp/ で始まるパスは、mcp: を宣言していなくても MCP 経由以外では 404 になります。このパスにはツールのハンドラ以外のルートを置かないでください。静的に配信される部分には影響しません
予約パスの一覧は Keelson Deploy Spec の予約 URL パス を参照してください。
項目 上限 ツールの数 1 アプリ 40 本 instructions4096 文字 ツールの description 1024 文字 ツールの input JSON にして 64 KB・入れ子 32 段 1 回の呼び出し 60 秒 応答の本文(2xx) 1 MiB 呼び出し回数 1 接続あたり 1 分 60 回 同時に実行される呼び出し 1 アプリ 10(Keelson の中継サーバー 1 台ごとの値。中継サーバーが増えるとアプリ全体ではこれより多く同時に届くことがあります)
回数と同時実行の上限を超えた呼び出しは、少し待ってから再試行するよう AI クライアントに返されます。上限はプランで変わりません。同時実行の 10 はアプリが受ける同時呼び出しの最大値ではないので、データベースの接続数などを 10 件前提で決めないでください。
症状 確認すること ツールが一覧に出ない その利用者にアプリの権限があるか(permission: manage のツールは管理権限が必要)。書き込みツールなら、同意画面で承認したか。mcp.enabled が true か。ワークスペースの MCP が停止されていないか(アプリの MCP タブの状態に表示されます) IP 制限のあるワークスペースで呼び出しが拒否される IP 制限は MCP 経由の呼び出しにも適用されます。claude.ai や ChatGPT からの呼び出しは利用者の PC ではなく各社のサーバーから届くため、そのままでは許可されません。IP 制御 のアクセス元を見直してください 「ツールの応答が不正」と表示される ハンドラが 2xx で JSON の本文を返しているか。本文が空・テキスト・1 MiB 超になっていないか ログインの後に接続できない AI クライアントが claude.ai または chatgpt.com の身元を名乗るものか。ログインしたアカウントがアプリを閲覧できるメンバーか デプロイで mcp の file が未対応のキーとして拒否される Keelson CLI が古いため。keelson upgrade で最新版にしてからデプロイし直します
外部システムとの連携 OpenAI などの API を呼ぶ、外部サービスの通知を受け取る、外部データベースに接続するなど、用途に応じて連携方法を選べます。
アプリから外部サービスへの通信に制限はありません。例外は SMTP のポート(TCP 25・465・587・2525)で、これらは常に遮断されます。必要な API キーをシークレット に設定し、アプリから呼び出します。外部サービス側の契約や呼び出し回数の制限は、そのサービスの条件に従います。
メールを送信するには、Keelson の Email SDK か、Resend・SendGrid・Mailgun など契約したメール送信サービスの HTTPS API を使います。契約したサービスでも SMTP 中継ホストは使えないため、SMTP のホストとポートではなく API クライアントを設定してください。
一方、外部のシステムからアプリを呼ぶ場合は、既定で Keelson のログインが必要です。ブラウザでログインできないシステムから呼び出すには、以下の設定を行います。
Webhook は、外部サービスで起きた出来事をアプリに通知する仕組みです。たとえば決済完了の通知を受けて、注文の状態を更新できます。
Webhook の受信には、webhook スコープのアプリトークンが必要です。送信元の署名がある場合も、このトークンを併用します。auth.endpoints を設定するだけでは、署名のみのリクエストを受け取れるようにはなりません。
まず、対象アプリのトークンを発行します。my-app はアプリの slug に置き換えてください。
keelson apps tokens create --app my-app --name webhook-client --scope webhook
アプリに POST /api/webhooks/incoming などの受信処理を実装します。次のパスをアプリの URL(例:https://acme--my-app.keelson.run)に付け、送信元の受信先として登録します。
送信元で設定できるもの 設定方法 任意の HTTP ヘッダー 受信 URL を /api/webhooks/incoming にし、X-Webhook-Secret: <発行したトークン> を付ける 受信 URL のみ 受信 URL を /api/webhooks/<発行したトークン>/incoming にする
URL にトークンを含めた場合、Keelson はトークン部分を取り除き、アプリの /api/webhooks/incoming に渡します。トークンを含む URL は秘密の値として扱ってください。これらのリクエストにログインユーザーの情報は付きません。
Keelson はトークンの有効性、対象アプリ、webhook スコープ、送信元 IP の制限を確認します。現在、Webhook のパスやメソッドを auth.endpoints で制限することはできません。受信処理で許可するパスとメソッドを確認してください。
送信元が署名を付ける場合は、署名シークレットを secrets で受け取り、アプリ側でも署名を検証します。Keelson のアプリトークンは、送信元の署名シークレットとは別のものです。
なお /api/webhooks/email と /api/webhooks/email-events はプラットフォーム予約のため、独自の Webhook の受信先には使えません。auth.endpoints には追加しないでください。
社内の別システムやスクリプトからアプリの API を呼ぶ場合は、アプリトークンを発行します。
keelson apps tokens create --app my-app --name batch-client --scope api --allowed-ip 203.0.113.0/24
my-app は対象アプリの slug、203.0.113.0/24 は実際の送信元 IP の範囲に置き換えます。
トークンは keelson_... の形式で、作成時に 1 回だけ表示されます
--scope api は /api/external/ 配下、--scope webhook は /api/webhooks/ 配下に対応します
--allowed-ip で送信元 IP を絞れます(CIDR、複数可)。ワークスペースやアプリの IP 制御とは別に、トークン単位で適用されます
同じ設定はコンソールのアプリ画面からも行えます。CLI の keelson apps tokens 配下には、一覧を表示する list、トークンを更新する rotate、失効させる delete があります
呼び出し側は Authorization: Bearer keelson_... を付けて、auth.endpoints で宣言したパスを呼びます。
curl -H "Authorization: Bearer keelson_xxx" https://acme--my-app.keelson.run/api/external/status
- path : /api/external/status
- /api/external/import # メソッド指定なし = すべて
Keelson は、トークンが有効で対象アプリ・用途に合っていること、送信元 IP が許可されていること、パスとメソッドが宣言に合っていることを確認してから、アプリにリクエストを渡します。
auth.endpoints のパスは完全一致ではなく、先頭の文字列で照合されます。たとえば /api/external/status は /api/external/status/detail や /api/external/status-old にも一致します。アプリ側でも受け付けるパスとメソッドを確認してください。宣言していない API は、api スコープのトークンでは呼び出せません。
Keelson の Email SDK を使うと、メール送信サービスを契約せずに、アプリからアプリの利用者へメールを送れます。パスワード再設定、申請の受付通知、承認依頼などの業務連絡に使います。
送信できるのは、そのアプリの利用者への業務上の連絡だけです(利用ポリシー 2.3)。マーケティングの一斉送信、購入した宛先リストへの送信、アプリを使っていない人への送信はできません。継続的に送る通知には、受信者が受信を停止できる手段を設けてください。
import * as email from "@keelsonhq/email" ;
const result = await email. send ({
text: "申請番号 1234 を受け付けました。" ,
// result.send_id を保存しておくと、配信結果と突き合わせられます
Python では from keelson import email で読み込み、email.send(...) を呼びます。Go では github.com/keelsonhq/go-sdk/email の email.New("", "") でクライアントを作り、Send を呼びます。インストールは Keelson SDK を参照してください。
接続先とトークン(KEELSON_EMAIL_TOKEN など)は、Keelson がデプロイ時に自動で設定し、SDK が読み取ります。keelson.yaml への追加設定は不要です。静的サイト・SPA には SDK を動かすサーバーがないため送れません
差出人は、既定では <アプリの slug>@mail.keelson.run です。表示名(from_name)と返信先(reply_to)は指定できます。Team プランでは、自社のドメインの許可したアドレスも差出人にできます(下記 )
1 通の宛先は To・CC・BCC の合計で 50 件までです。本文には text か html の少なくとも一方が必要です
送信の回数は、アプリごと・ワークスペースごとにそれぞれ 60 秒あたり 30 回までです
月ごとに送れる宛先数は、プランごとに決まっています(プランと制限 )。当月の使用量は、コンソールのワークスペース設定の「メール」で確認できます
Team プランでは、ワークスペースが所有するドメインのアドレス(例 [email protected] )を差出人にして送れます。ドメインはワークスペースあたり 10 件まで、差出人に使える許可アドレスはドメインあたり 20 件まで登録できます。設定は Owner / Admin が、コンソールのワークスペース設定の「メール」>「送信ドメイン」で行います。ドメインの DNS 設定を変更できる権限が必要です。
「ドメインを追加」でドメインを入力します。1 つのアプリだけに使わせる場合は「スコープ」でアプリを選びます。選ばなければ、ワークスペースのすべてのアプリが使えます。
「所有の確認」に表示された TXT レコードを DNS に追加し、「状態を確認」を押します。1 つのドメインを所有確認できるのは 1 ワークスペースだけです。
所有が確認されると、メールの署名(DKIM)用の CNAME レコードが 3 件表示されます。DNS に追加してください。検証は通常数分で終わります。状態は「状態を確認」を押すと確認できます。72 時間以内にレコードが見つからない場合は検証に失敗します。ドメインを削除して追加し直してください。
「許可アドレス」に、アプリが差出人に使うアドレスを追加します。
アプリでは、そのアドレスを from_address(Node・Python)または From(Go)に渡します。
from_name: "Example サポート" ,
text: "申請番号 1234 を受け付けました。" ,
差出人は送信のたびに確認されます。送信するアプリのワークスペースで検証済みのドメインの許可アドレスと完全に一致しない差出人(大文字・小文字は区別しません)は、送信を拒否します。許可アドレスを削除すると、次の送信から拒否されます
メールには自社のドメインの DKIM 署名が付き、DMARC の判定で差出人のドメインと整合します。返送先(SPF)には自社のドメインを使わないため、SPF は整合しません
既定の差出人 <アプリの slug>@mail.keelson.run は、許可アドレスの登録なしでそのまま使えます
ワークスペースが Team プランでなくなると、自社のドメインからの送信は拒否されます。登録したドメインと許可アドレスは残り、Team に戻すと再び使えます
バウンス・苦情と抑止リストは、既定の差出人と同じように働きます
送信できない場合、SDK はエラーを送出します。エラーメッセージにエラーコードが含まれます。
HTTP エラーコード 意味 400 RECIPIENT_SUPPRESSED宛先が、ワークスペースの抑止リストに載っています(下記 ) 403 EMAIL_SENDING_SUSPENDEDワークスペースのメール送信が停止されています。恒久的なバウンスや苦情が多いと、ワークスペース全体の送信が自動で停止します。解除はお問い合わせ ください 403 SENDER_DOMAIN_NOT_AVAILABLE差出人が自社のドメインですが、ワークスペースが Team プランではありません 403 DOMAIN_NOT_VERIFIED差出人のドメインが、送信するアプリのワークスペースで検証済みでないか、別のアプリに限定されています 403 SENDER_ADDRESS_NOT_ALLOWED差出人が、そのドメインの許可アドレスに登録されていません 422 RECIPIENT_LIMIT_EXCEEDED宛先が合計 50 件を超えています 429 RATE_LIMIT_EXCEEDED60 秒あたりの送信回数の上限に達しました。時間をおいて送り直します 429 MONTHLY_QUOTA_EXCEEDED当月の宛先数の上限に達しました。翌月にリセットされます 429 GLOBAL_RATE_LIMIT_EXCEEDED / GLOBAL_DAILY_QUOTA_EXCEEDEDKeelson 全体の送信量が一時的に上限に達しました。時間をおいて送り直します 502 SEND_OUTCOME_UNKNOWN送信されたかを確認できませんでした。届いている可能性があるため、自動では送り直さないでください
送ったメールが届いたか、宛先が存在しないなどの理由で返ってきたか(バウンス)、受信者が迷惑メールとして報告したか(苦情)を、Keelson がアプリの POST /api/webhooks/email-events に通知します。結果を使う場合は、このパスに受信処理を実装します。アプリトークンや auth.endpoints の設定は不要です。
恒久的なバウンスと苦情を受けた宛先は、受信処理の有無にかかわらず、ワークスペースの抑止リストに自動で載ります。以後、同じワークスペースのどのアプリからもその宛先には送れません(RECIPIENT_SUPPRESSED)。抑止リストは、Owner / Admin がコンソールのワークスペース設定の「メール」で確認・削除できます。
通知には署名が付いています。SDK で署名を検証してから内容を使います。署名の鍵 KEELSON_EMAIL_WEBHOOK_SECRET は Keelson が自動で設定します。
import * as email from "@keelsonhq/email" ;
// POST /api/webhooks/email-events の受信処理。rawBody は受け取った本文そのもの
const event = email. verifyEventWebhookBytes (
process.env. KEELSON_EMAIL_WEBHOOK_SECRET ! ,
if (event.event_type === "bounce" && event.bounce_type === "hard" ) {
// event.send_id で送信時の記録を探し、宛先を無効にする
Python では email.verify_event_webhook(body, headers, secret)、Go では email.VerifyEventWebhook(r, secret) を使います。署名は本文のバイト列に対して検証するため、JSON として解析し直す前の本文を渡してください。
項目 内容 event_id通知の ID。同じ通知が重複して届くことがあるため、重複の判定に使います event_typedelivered(届いた)・bounce(バウンス)・complaint(苦情)email_address対象の宛先 send_id送信時に返された send_id。送信の記録との突き合わせに使います bounce_typeバウンスのとき、hard(恒久的)か soft(一時的) detail補足の情報 provider配信に使った送信基盤の名前 timestamp発生時刻
受信処理が 2xx を返すと通知は完了します。5xx を返したときやアプリに届かなかったときは、時間をおいて合計 4 回まで試みます。4xx を返した通知は送り直しません。
PostgreSQL、MySQL、自前の libSQL に接続する場合は db.mode: none にし、接続情報をシークレットで渡します。詳しくはデータベース を参照してください。
Files / Media SDK の上限を超えるファイルは、S3 互換のストレージにアプリから直接保存します。認証情報はシークレットで渡します。
メールを受け取る アプリに専用のメールアドレスを持たせることができます。届いたメールは、Keelson がアプリのデータベースの表に 1 通 1 行で保存し、添付ファイルを Files に置きます。アプリは SQL で読むだけで、メールを受け取るコードは要りません。保存したメールを 1 通ずつ処理したい場合は、on_receive にバックグラウンドタスク の名前を書きます。
主な用途は、問い合わせの共有受信箱や、注文・請求のメールの読み取りです。独自ドメインのメールを Keelson で直接受けることはできません。Gmail・Google Workspace・Microsoft 365 から、アプリのアドレスへ転送します(アプリへ転送する )。
通常は AI エージェントに、届いたメールをどう扱うかを伝えると、keelson.yaml の設定と処理のタスクを書きます。
営業グループ(sales@)から転送される注文メールを保存して、1 通ごとに注文として登録してください。同じメールを 2 回処理しても、注文が重複しないようにしてください。
keelson.yaml に email.inbound を書いてデプロイします。受信には Managed SQLite(db.mode: libsql)が必要です。
command : "uvicorn main:app --host 0.0.0.0 --port $PORT"
on_receive : process-mail # 任意。tasks に宣言したタスク
command : "python process_mail.py"
項目 意味 email.inbound.enabledtrue で受信を有効にする。デプロイで受信アドレスを発行し、表 keelson_inbound_emails を作るemail.inbound.on_receive任意。tasks に宣言したタスクの名前。メールを保存するたびに、このタスクを起動する
次の場合はデプロイが拒否されます。
エラー 原因 email_inbound_requires_libsqldb.mode: libsql でないのに enabled: true にしたemail_on_receive_requires_enabledon_receive があるのに enabled が true でないemail_on_receive_unknown_taskon_receive の名前が tasks[].name のどれとも一致しない
on_receive を書いたアプリは、tasks があっても command と crons が無くて構いません(受信がタスクを起動するため)。添付ファイルの置き場は固定で、設定できません。
受信アドレスは、コンソールのアプリの Email 設定に表示されます。形は in+<ランダムな文字列>@inbound.keelson.run です。ランダムな部分はアプリの slug と関係が無く、アプリ名を変えてもアドレスは変わりません。
作り直す :コンソールから新しいアドレスを発行できます。古いアドレスはその場で退役し、以後そのアドレス宛てのメールは拒否されます。
受信をやめる :email.inbound を外した(または enabled: false にした)デプロイで、アドレスは退役し、二度と使えなくなります。まだ保存していないメールと、保存できずに保留しているメールは破棄します。保存済みの行と添付ファイルはそのまま残ります。
もう一度有効にする :新しいアドレスを発行します。転送の設定を新しいアドレスに直してください。
退役したアドレスは、どのアプリでも再利用しません。
1 通のメールが keelson_inbound_emails の 1 行になります。表はアプリ自身のデータベースにあるので、他の表と同じ接続で読めます。
列 内容 email_id主キー。受け取ったときに決まる schema_version行を書いたときの列の版。今は 1 received_at受け取った時刻(ISO 8601、UTC) envelope_to配送されたアプリの受信アドレス envelope_from配送に使われた送信元アドレス(エンベロープの送信元) from_address差出人のアドレス。X-Original-From があればそれ、無ければ From。認証済みの値ではない (後述 ) from_name差出人の表示名(同じヘッダーから) header_from生の From ヘッダー(転送グループが書き換えた後の値) reply_toReply-To ヘッダーto_addressesTo のアドレスの JSON 配列(転送されたメールでは共有受信箱のアドレス)cc_addressesCc のアドレスの JSON 配列subject件名 message_idMessage-ID ヘッダーin_reply_toIn-Reply-To ヘッダーreferences_headerReferences ヘッダーlist_idList-Id ヘッダーtext_bodyテキストの本文(UTF-8 に変換済み) html_bodyHTML の本文(UTF-8 に変換済み) body_truncatedどちらかの本文が 1 MiB を超えて切られたら 1 attachments添付ファイルの JSON 配列(無ければ []) spam_score簡易的な spam の採点。印だけ(spam ) auth_spf / auth_dkim / auth_dmarc受信サーバーが記録した SPF / DKIM / DMARC の結果
無いヘッダーは NULL です。符号化された件名やファイル名(日本語を含む)は復号して保存します。
to_addresses と cc_addresses はアドレスの配列です(表示名が無ければ name は null)。
attachments の各要素は次の形です。
[{ "attachment_id" : "att_01" , "filename" : "注文書.pdf" , "content_type" : "application/pdf" ,
"content_id" : null , "size_bytes" : 182344 , "files_key" : "inbound/<email_id>/att_01" ,
content_id は、HTML の本文から参照されるインライン画像に入ります。
SELECT email_id, received_at, from_address, subject
FROM keelson_inbound_emails
ORDER BY received_at DESC
SELECT json_extract( a . value , '$.filename' ) AS filename ,
json_extract( a . value , '$.files_key' ) AS files_key
FROM keelson_inbound_emails e, json_each( e . attachments ) a
添付ファイルは Files のキー inbound/<email_id>/<attachment_id> に置かれます。attachments の files_key がこのキーです。Files SDK で読みます。
from keelson import files
(attachments,) = conn.execute(
"SELECT attachments FROM keelson_inbound_emails WHERE email_id = ?" , (email_id,)
for att in json.loads(attachments):
data = files.read(att[ "files_key" ]) # bytes | None
import * as files from "@keelsonhq/files" ;
const { rows } = await db. execute ({
sql: "SELECT attachments FROM keelson_inbound_emails WHERE email_id = ?" ,
for ( const att of JSON . parse (rows[ 0 ].attachments)) {
const data = await files. read (att.files_key); // Uint8Array | null
添付ファイルは Files の書き込み上限(10 MiB)を超えることがありますが、読み取りはできます。添付ファイルはワークスペースのストレージに数えます。表の行は数えません。
keelson_inbound_emails は、受信を有効にしたデプロイで Keelson が作ります。移行やアプリのコードで自分で作らないでください。Keelson が作っていない同名の表が既にあると、デプロイが止まります。
表は利用者のものです。アプリから読み書き・削除できます。「対応済み」「担当者」などの状態は、email_id をキーにした別の表に持ちます。
Keelson は行を足すだけで、既存の行の書き換えや表の作り直しはしません。
email_id の主キーを外す、列を消す、トリガーを付ける、Files のキー inbound/ の下に自分のファイルを置く、のいずれかをすると、新しいメールを保存できず保留になります(保存できなかったメール )。
データベースをバックアップから復元すると、この表もその時点の中身に戻ります。
on_receive にタスクを書くと、メールを保存するたびに Keelson がそのタスクを起動します。タスクの payload はメールの ID だけです。
{ "attempt_no" : 1 , "payload" :{ "email_id" : "…" }, "schema_version" : 1 , "task_id" : "…" , "task_name" : "process-mail" }
タスクは email_id で keelson_inbound_emails の行を読みます。起動のされ方以外は、通常のバックグラウンドタスクと同じです(バックグラウンドタスク )。
タスクは少なくとも 1 回起動します。 同じ email_id が 2 回以上渡ることがあり、失敗した試行は再試行されます。処理済みのメールを記録し、その記録と処理の結果を 1 つのトランザクションで書きます。
email_id = json.loads(sys.stdin.readline())[ "payload" ][ "email_id" ]
database = os.environ.get( "KEELSON_DB_URL" , "file:local.db" ),
auth_token = os.environ.get( "KEELSON_DB_AUTH_TOKEN" , "" ),
"CREATE TABLE IF NOT EXISTS handled_emails (email_id TEXT PRIMARY KEY, handled_at TEXT NOT NULL)"
"INSERT INTO handled_emails (email_id, handled_at) VALUES (?, datetime('now')) "
"ON CONFLICT (email_id) DO NOTHING" ,
(subject,) = conn.execute(
"SELECT subject FROM keelson_inbound_emails WHERE email_id = ?" ,
conn.execute( "INSERT INTO orders (email_id, title) VALUES (?, ?)" , (email_id, subject))
conn.commit() # 処理済みの記録と注文を一緒に保存する
commit の前にタスクが失敗すると何も保存されず、再試行で最初からやり直します。外部 API には email_id を冪等キーとして渡します。
保存済みのメールの on_receive は、コンソールから起動し直せます。数え方は自動の起動と同じです。
on_receive で起動したタスクは、バックグラウンド実行の回数に数えません。実行時間は月間の合計実行時間に合算します。合計実行時間の枠を使い切っているとタスクは起動せず、コンソールにその旨が出ます(自動では再試行しません)。
処理が重いと合計実行時間を使い切り、定期実行ジョブも止まります。コンソールで月間の使用量を確認してください。
from_address は X-Original-From か From のヘッダーから取ります。このヘッダーには誰でも好きなアドレスを書けます。from_address を、利用者の本人確認や、そのメールに何を許すかの判断に使わないでください。 (例:「社長から来たメールなら支払いを承認する」)。表示と振り分けにだけ使います。
auth_spf・auth_dkim・auth_dmarc は受信サーバーの検査の記録です。転送で崩れることが多く、これも差出人の証明にはなりません。
独自ドメインのメールを Keelson で直接受けることはできません。今メールを受けている所で受けたまま、アプリのアドレスへ転送します。
Gmail の 設定 → すべての設定を表示 → メール転送と POP/IMAP で、アプリの受信アドレスを転送先に追加します。
Gmail が [email protected] から確認メールをそのアドレスへ送ります。コンソールのアプリの Email 設定の 最近届いたメール で確認コードを読みます。アプリが動いていなくても読めます。
Gmail に確認コードを入力し、転送を有効にします。一部のメールだけを転送する場合は、Gmail のフィルタで転送します。
確認メールも、他のメールと同じように表に保存されます。on_receive を使っている場合は、確認メールでもタスクが起動します。
メールを受けている Google グループ(例:support@)のメンバーに、アプリの受信アドレスを追加します。グループに届いたメールの写しがアプリにも届きます。
アドレスを追加できない場合は、Google Workspace の管理者が、組織外のメンバーをグループに追加できるように設定する必要があります。
元の差出人のドメインの DMARC ポリシーが厳しいと、Google グループは From をグループのアドレスに書き換え、元の差出人を X-Original-From に残します。from_address は X-Original-From を使うので、元の差出人が入ります。header_from には書き換え後の From、to_addresses にはグループのアドレスが入ります。
Microsoft 365 は、外部のアドレスへの自動転送を既定で止めています(送信の迷惑メールフィルターのポリシー)。転送する前に、管理者が許可する必要があります。許可していないと、転送したメールは 550 5.7.520 Access denied, Your organization does not allow external forwarding で戻ってきます。
Microsoft Defender ポータルで、送信の迷惑メール対策ポリシーの自動転送をオンにします。転送するメールボックスだけに適用する独自のポリシーを作るのが安全です。
そのメールボックスで、アプリのアドレスへの転送(Outlook の転送設定か受信トレイのルール)を設定します。メールフローのルールでも転送できます。
Microsoft 365 からの転送は Keelson では試していません。手順は Microsoft の文書に基づきます。
項目 上限 1 通の大きさ 添付ファイルを含めて 25 MiB。超えるメールは拒否される 本文 text_body・html_body はそれぞれ 1 MiB で切る(body_truncated = 1)添付ファイル 25 MiB の範囲で、1 つあたりの上限は無い 月間の受信数 ワークスペース単位で、全アプリの合計。下の表
受信の月間上限 (ワークスペース単位・UTC の暦月)
Starter Plus Team Business 受信数 / 月 500 通 3,000 通 10,000 通 30,000 通
重複を除いた後に 1 通 1 回数えます。80%・100%・150% に達すると、ワークスペースの Owner と Admin に通知します。
100% を超えたら :受信と保存は続けますが、超えた分のメールでは on_receive を起動しません。コンソールでそのメールに印が付きます。プランを上げた後に、コンソールから on_receive を起動できます。
150% に達したら :ワークスペースのアドレスがメールを拒否し、送信元にエラーが返ります。翌月 1 日 0 時(UTC)か、プランを変更すると受信を再開します。切り替わるまでの間に届いた数通は保存されることがあります。
表を消した、主キーを外した、トリガーで行を弾いた、inbound/ に別のファイルが既にある、などで表に書けなかったメールは、Keelson が保留します。コンソールのメールの履歴に、理由と直し方が出ます。表を直した後、コンソールから保存し直してください。
保留は 7 日、アプリあたり 1,000 通までです。保留が 1,000 通に達している間は、そのアプリのアドレスへの新しいメールを拒否します。
7 日を過ぎた保留のメールは「期限切れ」と記録し、メールと添付ファイルを消します。
コンソールのメールの履歴には、保存待ちのメール、メールとして読み取れなかったもの、受信をやめたために破棄したメールも出ます。
spam_score は簡易的な採点です。Keelson はこれで隔離や削除をせず、すべてのメールを保存します。転送したメールは SPF に落ちやすく、普通のメールにも点が付くことがあります。点が高いメールをどう扱うかは、アプリで決めてください。
コンソールを見る :アプリの Email 設定のメールの履歴を開きます。そこにあれば Keelson は受け取っています。状態(保留とその理由)を確かめます。
アドレスを確かめる :作り直す前のアドレスや、受信をやめたアプリのアドレスへのメールは拒否されます。
上限を確かめる :月間上限の 150% に達している、または保留が 1,000 通に達していると、新しいメールは拒否されます。25 MiB を超えるメールも拒否されます。
転送の設定を確かめる :Gmail の転送は、確認コードを入力するまで始まりません。Microsoft 365 は、管理者が許可しないと外部への転送を止めます。
Keelson より手前の認証検査 :SPF と DKIM の両方に落ちたメールや、送信元ドメインの DMARC ポリシーに落ちたメールは、Keelson に届く前に受信サービスが拒否します。このメールは Keelson に記録が残らず、送信元には通常エラーが返ります。メールの中身を変える転送でこうなることがあります。Google グループ経由の転送なら、こうした送信元のメールも届きます。
keelson dev email は、保存したメールのファイル(.eml)を、Keelson が受け取ったときと同じ形で手元のデータベースと Files に保存します。
export KEELSON_DB_URL = file:local.db
keelson dev email ./samples/order.eml
keelson dev email <file.eml> [--to <address>]
メールを Keelson と同じ規則で読み取り、KEELSON_DB_URL のデータベースの keelson_inbound_emails に 1 行 INSERT します。表が無ければ作ります(手元だけ)。
添付ファイルは KEELSON_FILES_DIR(既定 ./.keelson/files)の inbound/<email_id>/<attachment_id> に書きます。手元の開発では Files SDK がここを読みます。
KEELSON_DB_URL は手元を指す必要があります。file: の URL か、ホストが 127.0.0.1 か localhost の http://・libsql://・ws:// の URL です。それ以外や未設定のときは、何も書かずに終了コード 2 で終わります。
--to は受信アドレス(envelope_to)です。既定は [email protected] です。
出力には email_id・件名・添付ファイルの数と置き場が出ます。
email_id はメールの中身と --to から決まります。同じファイルをもう一度流すと Already stored と出て、終了コード 0 で終わります。
メールとして読み取れないファイルは終了コード 1 です。
on_receive は起動しません。keelson.yaml に宣言があれば、タスクを動かすコマンドを表示します。
keelson dev task run process-mail --payload '{"email_id":"…"}'
.eml ファイルは、メールソフトで元のメッセージをダウンロードして作ります(Gmail では メッセージのソースを表示 → 元のメッセージをダウンロード )。
フレームワーク別の注意点 このページでは、フレームワークごとの本番向けの起動方法と注意点を説明します。Web サーバーは、環境変数 PORT で指定されたポートで起動してください。データベースや通信方式に制約があるフレームワークもあるため、対応アプリと制約 も確認してください。
開発サーバーは、性能やエラー画面での内部情報の表示、終了時のリクエスト処理などに問題があるため、本番向けのサーバーを使用してください。
通常の設定は AI エージェントに任せられます。このページは、起動方法を確認したいときや、デプロイ時の問題を調べるときに、自分のフレームワークの箇所を参照してください。
0.0.0.0 と環境変数 PORT で指定されたポートで待ち受ける。 127.0.0.1 ではリクエストが届きません
起動コマンドにインストール処理を含めない。 依存パッケージは requirements.txt / pyproject.toml / package.json / go.mod などをもとに、ビルド時にインストールされます
停止は SIGTERM → 10 秒後に SIGKILL。 処理中のリクエストは 10 秒以内に終わらせます
worker 数はまず 1 にします。 増やす場合は、利用できる CPU・メモリとアプリの処理内容に合わせて調整します
デバッグモードは既定で無効にします。 デバッグ画面は環境変数(DB の認証トークンを含む)を表示することがあります
「Keelson 上か」の判別は KEELSON_MODE。 値が keelson ならプラットフォーム上です。実行環境の判定と、デバッグモードの有効・無効は分けて扱います
ON_KEELSON = os.environ.get( "KEELSON_MODE" ) == "keelson"
DEBUG = os.environ.get( "DEBUG" , "false" ).lower() == "true" # 既定は false
command : "uvicorn main:app --host 0.0.0.0 --port $PORT"
--reload は付けません(ファイル監視がメモリを消費し、二重起動することがあります)。worker は既定の 1 のままにします。
app.run() は開発サーバーです。gunicorn を requirements.txt に追加して起動します。
command : "gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 --graceful-timeout 9 app:app"
app:app はモジュール名とアプリオブジェクト名に置き換えます。--graceful-timeout 9 で 10 秒の SIGTERM 猶予に収めます。
Django は、外部 DB(PostgreSQL など)に接続する構成でのみデプロイできます。Managed SQLite(libSQL)には Django ORM 用のバックエンドがないため、Managed SQLite やファイル SQLite を DB にする構成は未対応です。
db.mode: none にし、接続情報はシークレット で渡します。起動は runserver ではなく gunicorn を使います。
command : "gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 --graceful-timeout 9 config.wsgi:application"
config.wsgi:application はプロジェクトの WSGI モジュールに置き換えます。DEBUG は既定で無効にし、静的ファイルは whitenoise で配信します(STATIC_ROOT を設定し、ビルドで collectstatic を実行)。ALLOWED_HOSTS = ["*"] は維持してください。詳しい設定は Deploy Spec を参照してください。
ファイル SQLite を使う構成では、sqlalchemy-libsql-native を使って Managed SQLite に接続する方法があります。この方法は実験的な扱いです。接続設定の変更に加えて、モデル・クエリ・マイグレーションが動作するかを確認してください。AI エージェントに、必要な変更と互換性の確認を依頼してください。
Streamlit は WebSocket が必須のため、現在は動きません。Gradio は 4 以上を検証中です。
NODE_ENV は自動設定されません。keelson.yaml で宣言します。未設定だと Express などがスタックトレースをレスポンスに含めます。
Keelson 上でのビルドには npm を使います。pnpm-lock.yaml / yarn.lock しかない場合は、事前チェックでデプロイが止まります。package-lock.json を生成し、npm で依存のインストールとビルドが成功するかを確認してください。静的サイトは、手元で pnpm や Yarn を使ってビルドしたものも配信できます。詳しくは依存関係のインストール を参照してください。
command : "npm start" # package.json: "start": "node server.js"
エラーハンドラでスタックを返さない
クライアント IP や HTTPS の判定に trust proxy を使う場合は、実際のプロキシ経路と転送ヘッダーに合わせて設定する。固定値 1 で正しく判定できるとは限りません(Express の公式ガイド )
アプリ独自のセッションや JWT に使うシークレットは secrets で宣言する
ビルドして next start で起動します。next dev は本番用ではありません。
command : "npm run start" # package.json: "start": "next start -p $PORT"
npm run build がビルド時に自動実行されます。.next/ が生成されることを確認します
"start": "next dev" になっていたら直します
KEELSON_DB_URL をサーバー側で読みます。NEXT_PUBLIC_* に入れるとブラウザに配布されます
Managed SQLite に接続する場合も、Prisma の provider は "sqlite" を使います。変更するのは接続方法です。ローカルファイルへの接続を、@prisma/adapter-libsql を渡した Prisma Client に変更し、KEELSON_DB_URL と KEELSON_DB_AUTH_TOKEN を使います(接続方法 )。
@prisma/adapter-libsql と @prisma/client は対応するバージョンにそろえます(6.x で検証済み)。アダプターの設定だけで、Prisma のマイグレーションがリモート DB に適用されるわけではありません。利用中のバージョンでのクエリの動作と、生成した SQL を Managed SQLite に適用する方法を、AI エージェントに確認してもらってください。
Keelson が go build -o /workspace/app . でビルドし、./app で起動します。
CGO_ENABLED=0 でビルドされます。mattn/go-sqlite3 などの cgo SQLite ドライバは使えません。Managed SQLite には純 Go の libSQL クライアントを使います
ListenAndServe を放置せず、signal.NotifyContext と server.Shutdown で 10 秒以内に処理中のリクエストを処理し切ります
GORM などの ORM を使っている場合は、接続先 DB とドライバの互換性を確認します。Managed SQLite に接続できない場合は、database/sql と純 Go の libSQL クライアントを使う実装に変更します
Vite、Next.js の静的エクスポート、Astro などは、手元でビルドした出力を assets.dir に指定してデプロイします。command のない静的サイトでは、Keelson 上で依存パッケージのインストールやビルドは行われません。
静的サイトには type: web が必要です。dist/ を .gitignore に入れていても、assets.dir に指定していれば送信対象に含まれます。設定例は keelson.yaml の設定 を参照してください。
静的な画面と API サーバーを組み合わせるハイブリッド構成でも、画面のファイルは手元でビルドしてからデプロイします。
デプロイと運用 デプロイする 作ったアプリを Keelson で使えるようにする操作を「デプロイ」と呼びます。初めてアプリを使うときや、変更した内容を反映するときに行います。
Keelson は、AI エージェント経由での操作を前提に設計されています。初期設定を済ませれば、AI エージェントに依頼するだけで、必要な設定の確認からデプロイ、動作確認まで進められます。
対応している アプリのソースコード
アプリのフォルダに置く設定ファイル keelson.yaml(なければ AI エージェントに作成を依頼できます)
Keelson CLI のインストールとログイン(クイックスタート )
アプリが必要とする API キーなどの値(環境変数とシークレット )
新規作成には Owner / Admin / Developer のロール、既存アプリの更新には、そのアプリの管理権限(manage)が必要です。
アプリのフォルダを AI エージェントで開き、次のように依頼します。Keelson のスキルの設定方法はクイックスタート にあります。
このアプリを Keelson にデプロイしてください。必要な設定を確認し、完了したらアプリの URL と動作確認の結果を教えてください。
エージェントには、次の内容を確認・実行してもらいます。
アプリが扱うデータの保存先や起動設定が Keelson に合っているか確認する
keelson.yaml を作成・更新し、必要な API キーなどの登録先を案内する
デプロイを実行し、完了まで確認する
失敗した場合はログを調べ、原因と対応方法を説明する
完了後に動作を確認し、確認した内容を報告する
初回デプロイでアプリが作られます。2 回目以降は、同じワークスペース内の keelson.yaml の slug に対応するアプリが更新されます。slug はアプリを識別する名前です。
Web アプリや静的サイトは、報告された URL を開き、画面表示や主な操作を確認します。確認する項目やエージェントへの依頼例はデプロイ後の確認 を参照してください。
定期実行だけのアプリは、画面を開く代わりに、コンソールの「定期実行」タブでスケジュールと実行結果を確認します。手動で試す方法は定期実行ジョブ にあります。
変更 反映のタイミング コード、keelson.yaml の設定 デプロイで反映 シークレット 保存後、次のデプロイで反映。「適用」でも、コードを再アップロード・ビルドせずに再デプロイして反映できる アプリ権限、IP 制御、公開 URL の変更 デプロイなしで反映。通常は 2 分以内。障害中の変更は復旧後に反映
公開 URL をアプリ内部でも使っている場合は、URL 変更後の確認 も参照してください。
エラーメッセージに含まれるエラーコード(code)や対処のヒント(hint)を AI エージェントに伝えると、原因の調査に役立ちます。ログの確認方法と症状別の対処はトラブルシューティング にあります。
更新の切り替え前に失敗した場合、以前のバージョンへのアクセスは維持されます。ただし、データベースに加えた変更は自動では戻りません。データベースの変更を含む場合は、更新と復元 の手順で状態を確認します。
エージェントを介さず、ターミナルから実行することもできます。
keelson deploy --new --secrets-from-env-file .env.keelson
# アップロードせずに設定とアーカイブ内容を確認する
keelson deploy --check --json
--secrets-from-env-file で指定したファイルはアーカイブから除外されます
複数のワークスペースに属している場合は --workspace <slug> を付けます
更新先のアプリを明示するには --app <slug> を付けます。アップロードするソースは、コマンドを実行したフォルダのものです
スクリプトから使う場合は keelson deploy --ndjson --yes を使うと、完了まで待って結果を 1 行 1 JSON で返します
ここからは、設定やログを詳しく確認するときの説明です。サーバーで画面や API の処理を行う Web アプリでは、次の処理が行われます。
検証 — keelson.yaml とアップロードするファイルを確認します
ビルド — 必要なライブラリをインストールし、実行に必要なファイルをまとめます。このまとまりを「コンテナイメージ」と呼びます(ビルドの上限は 600 秒)
起動 — 新しいコードと設定でアプリを起動します。この実行単位を「リビジョン」と呼びます
ヘルスチェック — アプリが応答するか、health.path(既定 /)と verify のパスで確認します
マイグレーション — DB の構造などを更新する db.migrate があれば実行します
切り替え — 利用者のアクセス先を新しいリビジョンに移します
静的サイト / SPA は、ビルド済みの HTML・JavaScript などを配信します。Web サーバーの起動は行いません。定期実行だけのアプリには Web のアクセス先を切り替える処理はなく、設定した時刻にジョブが実行されます。
データの保存先や起動設定を調整する例として、ローカルの SQLite ファイルから Managed SQLite への移行や、Keelson が渡す PORT を使う変更があります。詳しくは対応アプリと制約 を参照してください。
デプロイ後の確認 デプロイが完了したら、アプリを開き、普段使う操作ができるか確認します。AI エージェントには、画面や API が正常に応答するかの確認を依頼できます。
自分のアカウントでアプリを開けるか
一覧表示や検索など、主な操作ができるか
保存機能がある場合、テスト用のデータを保存して読み直せるか
利用者に共有する前には、その人がアプリを開ける権限を持っているかも確認します。自分のアカウントで開けても、他の利用者が開けるとは限りません(アプリ URL とドメイン )。
定期実行だけのアプリは、コンソールの「定期実行」タブで実行結果を確認します。
デプロイしたアプリの主な画面と API を確認してください。確認できたことと、まだ確認していないことを教えてください。データを変更する確認にはテスト用データを使ってください。
画面や API から応答が返っても、計算結果や業務上のルールが正しいかは別途確認が必要です。普段使う入力例と期待する結果を伝えると、エージェントも確認しやすくなります。
通常のアプリの URL は認証で保護されているため、ログイン情報を付けない curl では確認できません。keelson app curl は、CLI にログインした本人の権限でリクエストを送ります。
本人としてアプリにアクセスするための一時的な認証情報を「プレビュートークン」と呼びます。app curl は内部でトークンを取得するため、利用者が値を扱う必要はありません。
次のコマンドで、ページや API の応答を取得できます。
keelson app curl / # GET /
keelson app curl -i /api/items # ヘッダーも表示
データの登録・更新・削除やファイルのアップロードは、実際のアプリに変更を加えます。次は書き込みの例です。パスとデータは、確認するアプリに合わせます。
keelson app curl /api/items --method POST \
--data '{"name":"example"}' \
--header 'Content-Type: application/json'
レスポンス本文は標準出力、メソッド・URL・ステータスは標準エラー出力に出ます。-i を付けるとヘッダーも標準エラー出力に出るので、本文だけをファイルに落とせます
既定は GET。--method で POST / PUT / PATCH / DELETE を明示すると、有効期間 5 分の書き込みを許可するトークンが使われます
--data は書き込みメソッドとだけ併用できます。@ファイル名 でファイルから読みます
--form を使うとメソッドは POST になり、multipart の Content-Type は CLI が付けます(--header での上書きは不可)
パスは / で始める必要があります。絶対 URL と // で始まるパスは拒否されます。リダイレクトは追いません
/__keelson/media/... と /__keelson/assets/... も GET / HEAD で確認できます
対象のアプリを明示する場合は --app <slug>
エージェントには、成功を示すステータスだけでなく、返された内容の種類(Content-Type)も確認してもらいます。たとえば、存在しない JavaScript ファイルの代わりに SPA の HTML が返ると、200 でも画面は正常に動きません。
別の HTTP クライアントを使う、複数回リクエストする、有効期間を選ぶ、といった場合はトークンを直接発行します。
keelson preview # GET / HEAD のみ。既定 30 分
keelson preview --allow-writes # POST / PUT / PATCH / DELETE も可。既定 5 分、最大 10 分
keelson preview --json # トークン・URL・有効期限を JSON で
--json が返す token と app_url を別の HTTP クライアントで使います。トークンは Bearer トークンとして渡します。
curl --header 'Authorization: Bearer <token>' '<app_url>/api/items'
トークンは標準出力に 1 回だけ表示され、Keelson は保存しません。ログや報告書に残さないでください。keelson preview で発行できるトークンは、アプリ × 利用者につき 1 本です。もう一度発行すると、有効期限内でも前のトークンは取り消されます。keelson app curl は別の内部用のトークンを使うため、preview で発行したトークンを取り消しません。
現在配信中のデプロイを自分が作っていない場合、プレビュートークンの発行前に、ブラウザで開く承認 URL が案内されます。承認には、そのアプリの管理権限(manage)が必要で、管理権限がある本人が承認することもできます。
承認画面で対象アプリ、書き込みの許可、有効期間を確認し、トークンの発行を承認します。承認後、案内された --confirmation <id> を付けて同じコマンドを再実行します。
これらのコマンドで取得できるのは、本人の権限で送ったリクエストへの応答です。ブラウザでの見た目や操作、他の利用者のアクセス権限は別途確認します
静的サイトには書き込み先がないので、書き込みメソッドは拒否されます
読み取り用の GET でも、アプリ側の実装によってはデータの変更やメール送信が起こります。確認対象の処理をエージェントに調べてもらい、意図しない変更が起きるパスは避けます
環境変数とシークレット 外部サービスの API キーや接続先などを、アプリに設定できます。設定値をアプリに渡す仕組みを「環境変数」と呼びます。API キーなどの秘密の値は、Keelson の「シークレット」に登録します。
種類 例 どこに書くか 秘密でない設定値 NODE_ENV、LOG_LEVEL、公開 API の URLkeelson.yaml の env秘密の値 API キー、トークン、DB 接続文字列、Webhook の署名シークレット シークレット (コンソール / CLI / デプロイ時の env ファイル)
keelson.yaml はソースコードと一緒に管理するファイルです。秘密の値は含めず、シークレットに登録します。
このアプリに必要な設定値と API キーを整理してください。設定ファイルには名前と用途を記載し、私が値を入力するファイルを用意してください。入力後に Keelson への登録と反映をお願いします。
設定ファイルの作成、アプリ側で値を読み取る処理、Keelson へのシークレットの登録・反映まで、エージェントに依頼できます。秘密の値はチャットに貼る代わりに、手元の設定ファイルへ入力して、そのファイルから登録してもらいます。コンソールから自分で入力することもできます。
Keelson のスキルを設定した AI エージェントに、手元の env ファイルからシークレットを登録するよう依頼できます。初回デプロイ時の登録も、既存アプリの値の更新も依頼できます。
.env.keelson に入力した値を、このアプリのシークレットに登録して反映してください。値そのものはチャットやログに出力しないでください。
以下のファイルは書式の例です。必要なキーをエージェントに用意してもらい、値を入力します。
SLACK_WEBHOOK_URL = https://hooks.slack.com/...
自分で登録する場合は、既存アプリの「シークレット」タブで追加・更新・削除できます。保存後に表示されるのは名前と更新日時で、値は再表示されません。
CLI から登録する場合は、次のコマンドを使います。エージェントもこれらのコマンドで登録・反映できます。
keelson deploy --new --secrets-from-env-file .env.keelson
keelson deploy --secrets-from-env-file .env.keelson
# 値を登録し、アップロード・ビルドなしの再デプロイで反映
keelson secrets set --from-env-file .env.keelson --apply
--secrets-from-env-file で指定したファイルはアップロード対象から除外されます。秘密を含むファイルは Git に追加せず、値をコマンドに直接書くことも避けてください。コマンドに書いた値はシェル履歴に残ることがあります。
シークレットは保存しただけでは、既に動いているアプリに反映されません。エージェントには登録と反映をまとめて依頼できます。初回はデプロイ時に反映され、既存アプリでは次のいずれかで反映します。
コードも更新する場合は、keelson deploy でデプロイする
値だけを反映する場合は、コンソールに表示される「未反映の変更があります」の 適用 ボタンを押す
CLI で登録と反映をまとめて行う場合は、上の secrets set --apply を使う
「適用」と --apply は、コードを再アップロード・ビルドせずに再デプロイします。最後に成功したデプロイの実行用ファイル(コンテナイメージ)を使い、新しい値でアプリを起動します。完了後は、API キーを使う操作などが動くか確認します。
ここからは設定ファイルとコードの詳細です。秘密でない値は、エージェントに keelson.yaml の env への記載を依頼できます。
値は必ず引用符で囲みます(数値・真偽値も)。引用符がないとデプロイが拒否されます
KEELSON_ で始まる名前は書けません(Keelson が設定します)。PORT は書いても無視され、Keelson の値が使われます
変更は次のデプロイで反映されます
keelson.yaml の secrets には、アプリが使うシークレットの名前・用途と、登録が必要な条件を記載できます。値は書きません。この宣言は任意です。 宣言しなくても、登録したシークレットは環境変数としてアプリに渡されます。
宣言すると、必要な設定が分かりやすくなり、登録漏れをデプロイ時に検出できます。エージェントに、アプリが使うキーと必須条件の整理を依頼できます。
description : "OpenAI API key"
- name : SLACK_WEBHOOK_URL
description : "通知先の Slack Webhook"
- all_of : [ OPENAI_API_KEY ]
message : "OPENAI_API_KEY を設定してください"
items は名前と用途の一覧で、コンソールにも表示されます。ここに書くだけでは必須にはなりません
required はデプロイに必要な条件です。条件を満たすシークレットが未登録だと、理由が表示され、デプロイは失敗します。この例では OPENAI_API_KEY が未登録だと「OPENAI_API_KEY を設定してください」と表示されます。値を登録してから、もう一度デプロイします
SLACK_WEBHOOK_URL は一覧にありますが、必須条件には含まれていないため、未登録でもこのチェックではデプロイを止めません
required を書かない場合、Keelson はこの必須チェックを行いません。必要な値が不足していてもデプロイ時のチェックでは検出されず、アプリの起動時や API キーを使う操作時にエラーになることがあります。
範囲(スコープ) 設定場所 用途 ワークスペース コンソールの「シークレット」 全アプリ共通の値(共有 API キーなど) アプリ アプリ画面の「シークレット」タブ そのアプリだけの値、またはワークスペースの値の上書き
同じ名前があれば アプリ > ワークスペース > env の順で優先されます。アプリ画面のシークレットタブには、どちらのスコープから来た値かが表示されます。
env もシークレットも、サーバー側のコードから環境変数として読み取ります。
api_key = os.environ[ "OPENAI_API_KEY" ]
const apiKey = process.env. OPENAI_API_KEY ;
env もシークレットも、ビルド(依存関係のインストール、npm run build)には渡りません。ビルドが読めるのはアップロードしたソース一式だけです。
フロントエンドのビルドに埋め込む公開値(VITE_API_URL など)は、ソース内の設定ファイルに書きます。ブラウザに配布される値なので、ここに認証情報を置かないでください。
Keelson はプラットフォーム管理の変数を各アプリに設定します。自分で定義または上書きしないでください。
変数 内容 PORTWeb アプリの待ち受けポート。 TZワークスペースのタイムゾーン。 KEELSON_MODEプラットフォームモードを示す値。 KEELSON_APP_IDアプリの内部 ID。 KEELSON_WORKSPACE_IDワークスペースの内部 ID。 KEELSON_TENANT_IDKEELSON_WORKSPACE_ID の互換用別名(値は同じ)。KEELSON_DEPLOY_ID現在のデプロイの内部 ID。 KEELSON_APP_URLアプリの標準 URL。 KEELSON_DIRECTORY_BASE_URLDirectory API の呼び出し先 URL。
機能を有効にすると追加の変数が設定されます。完全な一覧、各変数の設定条件、互換性のために残されている変数は環境変数一覧 にあります。
NODE_ENV は自動設定されないため、アプリが必要とする場合は env に記載します。
アプリ URL とドメイン Web アプリや静的サイトには専用の URL が割り当てられ、デプロイ後に利用者へ共有できます。自社で管理するドメインを使うこともできます。
標準の URL は次の形式です。slug は、URL などに使う識別名です。
https://<ワークスペース slug>--<アプリ slug>.keelson.run
ワークスペースの slug が acme、keelson.yaml の slug が dashboard なら https://acme--dashboard.keelson.run です。HTTPS の証明書は Keelson が管理します。
URL は、コンソールのアプリ画面、デプロイ完了時の AI エージェントの報告、keelson status で確認できます。
URL を知っているだけでは開けません。ワークスペースにログインし、そのアプリの閲覧権限を持つメンバーだけが開けます。IP 制御を設定していれば、許可されたネットワークからのアクセスに限られます。
App User にはアプリの URL を別途共有する 必要があります。App User はコンソールを開けないため、自分で URL を確認する手段がありません。上のいずれかの方法で URL をコピーし、チャットやメールで本人に送ってください。
アプリ作成後も URL は変えられます(Owner / Admin)。コンソールのアプリ設定「公開 URL」から行います。
変更すると以前の URL からは開けなくなり、新しい URL への自動転送もありません。利用者に新しい URL を共有し、ブックマークや外部サービスの設定を更新します。影響を確認するチェックを付けてから変更します。
以前の URL は 30 日間予約され、他のアプリが同じ名前を使えません。その間のアクセスには、利用できなくなったことを示す 410 Gone が返ります。30 日後に自動で解放されます
URL の変更にはコンソール、または keelson apps rename <new_slug> を使います。keelson.yaml の slug はデプロイ先のアプリを識別する名前で、これだけを変えても URL は変わりません。--app で対象を指定しない場合、次のデプロイは変更後の slug に対応するアプリを探すため、元のアプリを更新できなくなります。コンソールでアプリの識別名も変更した場合は、次のデプロイ前に keelson.yaml の slug を合わせます
ワークスペースの slug も設定から変更できますが、既存アプリの URL は変わりません 。新しいワークスペース slug の形式に揃えたい場合は、アプリごとに公開 URL を更新します。
Team プランでは、app.example.com のような自社のサブドメインでアプリを利用できます。設定には、ドメインの管理画面で DNS を変更できる権限が必要です。社内のドメイン管理者に依頼する場合は、Keelson が表示する設定値を共有します。
対象: Team プラン。ワークスペース合計で 10 件まで、1 アプリに 1 ドメイン
サブドメインのみ。ルートドメイン(example.com)とメールドメインは対象外。自社のドメインからメールを送るには自社のドメインから送る を参照
カスタムドメイン経由でも、認証・権限・IP 制御は同じように適用されます
設定は次の順で行います。
Owner または Admin が、コンソールのアプリ設定か keelson domains add <hostname> [--app <slug>] でドメインを登録します。登録すると、DNS に設定する CNAME の転送先が表示されます
DNS 事業者の設定で、登録したサブドメインの CNAME を表示された転送先へ向けます。本番環境の転送先は custom-origin.keelson.run です。コンソールまたは CLI に表示された値を使用してください
コンソールの状態表示か keelson domains verify <hostname> [--app <slug>] で有効になったことを確認します。有効化には数分かかることがあります
所有権の確認、HTTPS 証明書の発行、配信の設定は Keelson が自動で行います。
メール内のリンクなど、アプリが自分の URL を組み立てる場合の実装方法です。設定は AI エージェントに依頼できます。
アプリの標準 URL は環境変数 KEELSON_APP_URL で渡されます。リクエストの Host ヘッダーは内部のホスト名になるので、絶対 URL が必要な場面(メール内のリンク、リダイレクト、og:url)では KEELSON_APP_URL を使います。
base_url = os.environ[ "KEELSON_APP_URL" ] # 例: https://acme--dashboard.keelson.run
ローカル開発では設定されません。「Keelson 上で動いているか」の判別には KEELSON_MODE を使ってください。
公開 URL を変更しても、動いているアプリの環境変数はその場では更新されません。KEELSON_APP_URL を使うアプリは再デプロイし、メール内のリンクや移動先が新しい URL になっているか確認します。
カスタムドメインを設定しても、KEELSON_APP_URL は標準 URL のままです。メールのリンクなどにもカスタムドメインを使いたい場合は、その URL をアプリ側の設定値として持つようエージェントに依頼します(環境変数とシークレット )。
アプリの状態とログ アプリが使える状態か確認したり、不具合の原因を調べたりするときは、コンソールの状態表示とログを確認します。ログには、アプリの処理やエラー、アクセスの記録が残ります。
コンソールのアプリ一覧とアプリ画面に、状態がバッジで表示されます。
状態 意味 稼働中 最近のアクセスにより、「同時に使えるアプリ数」の枠を 1 つ使っている スリープ中 デプロイ済みで、最近のアクセスによる枠を使っていない。停止しているアプリはアクセス時に自動で起動する 配信中 静的サイト / SPA を配信している。画面のファイルは Keelson が直接返す サスペンド 手動で停止した状態。アクセスがあっても起動・再公開しない 。データ・URL・設定は保持される 起動中 / デプロイ中 起動・停止の切り替え、または新しいコードや設定の反映を処理している 未デプロイ アプリは作られているが、まだデプロイされていない エラー 直近のデプロイまたは実行に失敗した。アプリ画面に原因が表示される 削除中 削除処理中。完了すると一覧から消える — 定期実行だけのアプリ。ジョブごとの実行結果は「定期実行」タブで確認する
「稼働中」「スリープ中」は利用状況の表示で、サーバーのプロセスが起動しているかを直接示すものではありません。Web アプリは、アクセスがない状態が続くと停止し、次のアクセスで起動します(アプリが動くタイミング )。
通常は、直近 5 分にアクセスがあったアプリが枠を使います。優先起動で予約した枠は、アクセスがなくても確保されます。枠が空いていないときは、空くまで待つよう案内する画面が表示されます。予約していない枠は、そのアプリへのアクセスが約 5 分途絶えると空きます。
「エラー」は直近のデプロイの失敗を示す場合もあり、以前のバージョンが使えることがあります。「概要」の失敗内容と、アプリを実際に開けるかを合わせて確認します。
一時的に止めたいアプリは、アプリ画面の「設定」→「サスペンド」でサスペンドします。対象は Web アプリと静的サイト / SPA です。サスペンド中は、アクセス・Webhook・cron のいずれでも起動せず、静的ファイルも配信されません。Keelson の標準 URL には停止ページが表示され、独自ドメインの配信も止まります。データ・URL・設定は削除されません。
再開はアプリ画面のヘッダーの「再開」から行います。静的サイトや SPA はサスペンド中にデプロイしても停止状態を維持し、明示的に再開したときに配信へ戻ります。静的ファイルの停止と再公開は順次反映されるため、操作後に配信状態が切り替わるまで少し時間がかかることがあります。
定期実行だけのアプリには、コンソールのサスペンド操作はありません。各ジョブの enabled を false にしてデプロイすると、定期実行を止められます。再開するときは true に戻してデプロイします(定期実行ジョブ )。
アプリ画面のヘッダーの「優先起動」を ON にすると、「同時に使えるアプリ数」の枠を常に 1 つ予約します。枠が埋まっていて起動できない、という状態を防げます。
枠を予約していても、アプリはアクセスがない状態が続くと停止します。次のアクセス時には起動を待つことがあります
有料契約中は Plus 以上で、枠数より 1 つ少ない数まで設定できます。トライアル中は全プランで 2 本まで設定できます
調べたいことに合わせて、次の場所を確認します。
調べたいこと 確認する場所 記録される内容 デプロイが失敗した理由 「デプロイ」の各デプロイにある「詳細」 失敗の要約と、keelson.yaml についての警告などの利用者向けメッセージ。「詳細」は失敗したデプロイと警告のあるデプロイにだけ出ます アプリ使用中のエラー 「ログ」のアプリログ アプリが出力した処理の記録やエラー(標準出力・標準エラー) 利用者がアクセスを拒否された理由 「ログ」のアクセスログ 誰が・いつ・どのパスにアクセスし、許可・拒否されたか 定期実行が成功したか 「定期実行」の実行履歴 実行ごとの開始時刻・結果・所要時間・ログ
AI エージェントには、アプリ名・発生時刻・起きたことを伝えて調査を依頼できます。
このアプリで[日時]に[操作]をするとエラーになりました。状態とログを確認し、原因と対応方法を教えてください。
アプリログは Web と定期実行(cron)を切り替えられます。画面には直近 200 行を表示し、エクスポートでは最大 5,000 行を取得できます。アクセスログは、利用者・機械(アプリトークン)・Webhook で絞り込めます。閲覧できる期間はプラン によって異なります。
CLI からは keelson logs で取得できます。エージェントが処理しやすい JSON 形式でアプリログを取得するには、keelson logs app <slug> --json を使います。デプロイ失敗時に確認するログはトラブルシューティング にまとめています。
「デプロイ」タブに過去のデプロイが並び、各デプロイのソースをダウンロードできます。失敗したデプロイと警告のあるデプロイには「詳細」も出ます。
コードを前のデプロイに戻す操作を「ロールバック」と呼びます。データベースの内容は戻らず、静的サイト / SPA は以前のファイルを再デプロイする必要があります。手順と戻せる範囲は更新と復元 にまとめています。
「再デプロイ」(アプリ画面ヘッダー)は、最後に成功したデプロイの実行用ファイルを使って起動し直す操作です。シークレットの「適用」も、コードを再アップロード・ビルドせずに再デプロイして反映します(環境変数とシークレット )。
アプリを廃止するときは「設定」→「危険な操作」から削除できます。ブラウザでの承認が必要で、利用者自身で取り消すことはできません。削除前に取り出すデータと保持期間は更新と復元 を参照してください。一時的に止める場合は、上の「サスペンド」を使います。
更新と復元 アプリの変更を反映したり、不具合が起きたときに以前のコードやデータへ戻したりできます。やりたいことに合わせて操作を選びます。
操作には、そのアプリの管理権限(manage)が必要です。データベースの復元とアプリの削除にはブラウザでの承認も必要です。
コードを戻しても、データベースやファイルは以前の状態に戻りません。 詳しい範囲は、後半の何が戻り、何が戻らないか で確認できます。
AI エージェントには、変更内容と確認してほしい操作を伝えます。
この変更を Keelson に反映してください。デプロイ前に設定とアップロード対象を確認し、完了後に[操作]ができるか確認してください。
手元の開発環境で変更内容を確認します
エージェントにデプロイを依頼します。CLI では keelson deploy --check --json で設定とアップロード対象を事前確認し、keelson deploy で反映できます
完了したらアプリを開き、変更した操作を確認します。定期実行だけのアプリは実行履歴を確認します(デプロイ後の確認 )
切り替え前に失敗した場合、以前のバージョンへのアクセスは維持されます。ただし db.migrate が途中まで実行された場合、その変更は残ります(下の「DB の構造を変える」)。
変更が反映されるタイミング(シークレットは保存後にデプロイまたは「適用」が必要、など)はデプロイする を参照してください。
コードを以前のデプロイに戻す操作を「ロールバック」と呼びます。対象にできるのは、実行用のファイルをまとめた「コンテナイメージ」が残っている、過去の成功したデプロイです。
エージェントには「[不具合]が起きたので、前のコードに戻せるか、データへの影響も含めて確認してください」と依頼できます。CLI の操作は次のとおりです。
keelson rollback # 直前の成功したデプロイに戻す
keelson rollback <deploy_id> # 指定したデプロイに戻す
ビルドし直さず、対象デプロイのイメージと keelson.yaml の設定でアプリを起動します
対象にできるのは、イメージを持つ完了済みのデプロイだけです。静的サイト / SPA のデプロイと、古い方式で作られたデプロイはロールバック先にできません
シークレットは現在の値が使われます
対象デプロイの keelson.yaml に db.migrate があれば、ロールバックでも切り替え前に実行されます。DB に一切触れない操作ではありません
データベースは戻りません。 更新時に DB の構造(スキーマ)を変えていた場合、戻したコードがその構造で動くか確認が必要です。列の追加でも制約や既定値によって影響が出るため、エージェントに互換性の確認を依頼します。必要に応じて DB の復元も検討します
デプロイ進行中は実行できません
デプロイの一覧はコンソールの「デプロイ」タブにあり、各デプロイのソースをダウンロードできます。
静的サイト / SPA を戻すには、以前の成果物をもう一度デプロイします。Git で前のコミットに戻して手元でビルドし直すか、「デプロイ」タブから以前のデプロイのソース(assets.dir の中身と keelson.yaml)をダウンロードします。ダウンロードしたアーカイブを使う場合は、展開して keelson.yaml のあるフォルダで keelson deploy を実行します。再ビルドは不要です。
Managed SQLite(db.mode: libsql)のデータは、コンソールのアプリ画面にある「復元ポイント」から戻します。
復元ポイントのタイムラインから時点を選びます。日次バックアップ、手動で保存した状態(スナップショット)、指定した時刻への復元(PITR)のいずれかです(プランごとの保持世代数と復元窓はプランと制限 )
選択した過去の復元ポイントをダウンロード して、中身を確認することもできます。この操作で取得するのは、現在の DB ではありません
復元 を実行します。ブラウザでの承認が要ります
復元後、アプリを開いてデータを確認します
復元で起きること:
復元の切り替え中は、一時的に DB への書き込みができなくなります。 利用者に案内し、利用の少ない時間帯に実行してください
その時点以降の書き込みはすべて消えます。 消したデータだけを戻す操作ではありません。現在のデータも残しておきたい場合は、復元を実行する前に現在の DB の手動スナップショットを作成し、そのスナップショットをダウンロードします。復元後に必要な変更を移す作業は、エージェントに相談できます
復元前の状態は 72 時間保持され、その間は復元を取り消せます
復元は 1 つのアプリの DB だけに効きます。他のアプリには影響しません
Files / Media のファイルと外部 DB は対象外です
大きな変更の前に手動スナップショットを作ると、戻す時点を残せます(1 アプリ 5 回/日)。
保存する項目の追加など、DB の構造を更新する処理を「マイグレーション」と呼びます。コードを戻したときにも動くよう、エージェントには次の確認を依頼します。
DB の構造を変更する場合は、更新前のコードでも動くか、失敗後に再実行しても問題がないかを確認してください。復元が必要になる変更は、実行前に影響と戻し方を教えてください。
db.migrate に書いたコマンドは、デプロイやロールバックで新しいバージョンへ切り替える前に実行されます。
失敗すると以前のバージョンへのアクセスは維持されます。ただし、途中まで実行された DB の変更は自動では戻りません 。keelson logs deploy <deploy_id> のログと DB の状態を確認してから修正します
同じ処理を繰り返しても重複した変更が起きないようにします。この性質を「冪等性」と呼びます。適用済みの変更を記録する仕組みや IF NOT EXISTS などを使い、途中で失敗した場合も確認します
列やテーブルを追加する場合も、旧コードとの互換性を確認します。列の削除や型の変更など影響の大きい変更は、直前にスナップショットを作成し、利用の少ない時間帯に行う方法を検討します
「止める」と「消す」は別の操作です。
操作 何が起きるか 戻せるか サスペンド (Web アプリと静的サイト / SPA の「設定」→「サスペンド」)アクセス・Webhook・cron のいずれでも起動しない。URL には停止ページが出る。データ・URL・設定は残る 「再開」でいつでも戻せる 削除 (「設定」→「危険な操作」)アプリ本体・URL・デプロイ履歴・シークレットが消える。ブラウザでの承認が要る 戻せない
定期実行だけのアプリには、コンソールのサスペンド操作はありません。各ジョブの enabled を false にしてデプロイすると、定期実行を止められます。再開するときは true に戻してデプロイします(定期実行ジョブ )。
削除の前に取り出しておくもの:
DB のデータ — 現在のデータが必要なら手動スナップショットを作り、その復元ポイントからダウンロード
Files のファイル — アプリにダウンロード処理を用意して取り出します
Media のファイル — アプリが記録したファイル ID から閲覧用リンクを作り、削除前に保存します。Files / Media とも、コンソールや CLI には一覧・ダウンロード機能がありません(ファイルとメディア )
ソースコード — Git、または「デプロイ」タブの各デプロイからダウンロード
シークレットの値 — 保存後は再表示されません。登録時の保管先や発行元で、必要な値を確認します
削除後、DB のバックアップ・Files・非機密の構成メモ(アプリ名、URL、cron 定義、環境変数とシークレットの名前 )は 7 日間隔離保持されますが、これは誤削除への裁量対応であり、復元の保証ではありません。
契約が終了した場合のアプリの扱いは料金と契約の運用 を参照してください。
表の「ロールバック」はコードを前のデプロイに戻す操作、「DB の復元」は Managed SQLite を復元ポイントに戻す操作です。
対象 ロールバックで戻るか DB の復元で戻るか 備考 コード(イメージ) 戻る 戻らない ビルドし直さず、対象デプロイのイメージを起動する。静的サイト / SPA は対象外 keelson.yaml の設定(env、crons、assets、health)戻る 戻らない 対象デプロイ時点の設定が使われる シークレットの値 戻らない 戻らない 常に現在の 値が使われる。コンソールで手で戻す Managed SQLite のデータ 戻らない 戻る 日次バックアップ、手動スナップショット、PITR(時刻復元) db.migrate で加えたスキーマ変更戻らない 戻る 復元ポイントの時点の DB 構造になる Files SDK のファイル戻らない 戻らない バックアップの対象外。アプリ側で保持する Media SDK のファイル戻らない 戻らない 上書き不可。差し替えは新しいファイルを保存する 外部 DB(PostgreSQL など) 戻らない 戻らない 外部サービス側のバックアップで戻す 外部サービスへの変更(Slack 投稿、メール送信、決済) 戻らない 戻らない ロールバックでは取り消されない。再実行時の重複に注意 アプリ権限、IP 制御、公開 URL 戻らない 戻らない デプロイと独立した設定。手で戻す
トラブルシューティング デプロイに失敗したときや、アプリが期待どおりに動かないときの確認方法をまとめています。AI エージェントには、起きたこととエラーメッセージを伝えて、原因の調査を依頼できます。
Keelson のスキルを設定した AI エージェントは、CLI を通じてアプリの状態、デプロイログ、アプリログ、アクセスログを取得できます。CLI にログインしたアカウントの権限で確認するため、対象アプリのログを閲覧できる権限が必要です。ログを自分で探して貼り付けなくても、アプリ名と発生した日時、症状を伝えて調査を依頼できます。
このアプリで[操作]をすると[症状]が起きます。発生したのは[日時]です。状態とログを確認し、原因と対応方法を教えてください。
エラーコード(code)、メッセージ(message)、対処のヒント(hint)が表示されていれば、一緒に伝えます。サービス側の障害など、アプリの修正では解決しない場合は、サポートに問い合わせる の情報をまとめます。
コンソールでは、アプリ画面の「概要」に失敗の要約、「デプロイ」の各デプロイにある「詳細」に失敗の詳細、「ログ」にアプリログがあります。まず概要を確認し、必要に応じてエージェントに詳細を調べてもらいます。
deploy_id はデプロイを識別する ID で、CLI の出力やコンソールの「デプロイ」タブで確認できます。
keelson status # アプリと直近デプロイの状態
keelson diagnose <deploy_id> # 失敗したデプロイの診断
keelson logs deploy <deploy_id> # 進行ログと失敗したデプロイの詳細
keelson logs app <slug> # アプリの標準出力・標準エラー
起動中にアプリが終了した場合も、keelson logs deploy や keelson diagnose から保存済みの起動ログを確認できます。エラーが起きたコードの位置や、必要な設定が足りないことなどが記録されます。
保存されるログの範囲
失敗したデプロイでは、ビルドや起動の詳細が保存されます。依存パッケージや Dockerfile、シークレット、設定、マイグレーションのエラーを後から調べるときにも使えます。起動時の例外の記録(traceback)やプロセスエラーは、保存済みの起動ログを確認します。
成功したデプロイのビルド出力は保存されません。進行ログも保存済みの失敗詳細もない場合は、ログがない理由が表示されます。
止まった場所 見るもの よくある原因 アップロード前(CLI の事前チェック) コマンドの出力 Go アプリに go.mod がない、Node アプリに pnpm / yarn 用ロックファイルしかない、command に pip install、db.mode がない、env の値が引用符なし 検証 code と messageworkers / databases が残っている、予約名、プラン上限ビルド デプロイログ 依存の解決失敗、package.json と package-lock.json の不一致、非公開のパッケージ配布先(private registry)、cgo が必要な Go パッケージ、ビルドスクリプトのエラー 起動 keelson logs deploy <deploy_id> の保存済みのアプリの起動ログ0.0.0.0 で listen していない、PORT のハードコード、未設定のシークレットで例外ヘルスチェック 保存済みのアプリの起動ログ、その後にアプリログ アプリが起動中に終了、/ が 5xx、起動が完了せずヘルスチェックの制限時間を超える マイグレーション デプロイログ db.migrate の SQL エラー。以前のバージョンへのアクセスは維持されますが、マイグレーションが加えた DB の変更は自動では戻りません 。DB の状態を確認してから直します動いているが期待どおりでない アプリログ、アクセスログ 下の「よくある失敗」
Ctrl-C で止まるのは、このクライアントによる監視だけです。デプロイはサーバー側で続いています。
そのまま新しいバージョンへ切り替わることがあるため、CLI に表示された deploy_id で進行状況を確認します。
keelson status <deploy_id>
新しいバージョンを使わない場合は、デプロイの完了後に以前のコードへ戻します。コンテナイメージが残っている過去の成功したデプロイには、次のコマンドで戻せます。DB の変更は戻りません。
keelson rollback --app <slug>
静的サイト / SPA はロールバックの対象外です。以前のファイルを再デプロイします。手順は更新と復元 を参照してください。
戻せるデプロイがない場合など、いったん利用を止めたいときは、デプロイ完了後にサスペンドします。
keelson app stop --app <slug>
手元と Keelson で設定や保存先が異なる可能性があります。エージェントには、次の点を確認してもらいます。
手元からの接続だけを受け付けている — 待ち受けアドレスを localhost から 0.0.0.0 に変える
接続を受け付けるポート番号をコードで固定している — PORT 環境変数から読む
ローカルにしかないファイルに依存している — .env、ローカルの DB ファイル、.gitignore 済みのファイル。keelson deploy --check --json の archive.excluded で、何が除外されたか分かります
環境変数が未設定 — ローカルの .env にだけある値は Keelson にはありません。secrets に宣言して値を設定する
ローカルの SQLite ファイルを使っている — /tmp やアプリディレクトリのファイルは再起動後に残りません(/data は存在せず、作成もできません)。Managed SQLite への移行を検討する
Keelson の Node ビルダーは npm を使うため、依存を固定するには npm 用の package-lock.json が必要です。エージェントに、プロジェクトのルートで npm install を実行して package-lock.json を生成し、依存関係の整合性を確認してから再デプロイするよう依頼します。生成したファイルはソースコードと一緒に管理します。
pnpm-lock.yaml や yarn.lock は削除しなくてかまいません。package-lock.json と同居していてもデプロイでき、ビルドには package-lock.json が使われます。
保存先がアプリのサーバー内のファイルになっていないか確認します。/tmp やアプリディレクトリのファイルは、再起動・再デプロイ・アイドル停止で失われます。データベース か Files / Media SDK に置きます。
サーバー側でレスポンスを返した後に続ける処理は、最後まで実行されることが保証されません。また、アプリ内のタイマーは、アプリの停止中には動きません。
エージェントに、そのリクエストで必要な処理は応答を返すまでに完了させ、応答の後に続ける処理はバックグラウンドタスク に投入し、定期的な処理は Keelson の定期実行ジョブへ移すよう依頼します。未処理の内容を DB に保存して定期実行ジョブで処理する方法もありますが、次の実行まで待ち時間が生じます。ブラウザ側のタイマーは、この制約の対象外です。詳しくはアプリが動くタイミング を参照してください。
スケジュールがプランの最小間隔より短くないか(デプロイ時に拒否されます)
前回の実行が終わっていないか(重複実行はスキップされます)
月間実行回数の上限に達していないか(当月はスキップ)
アプリがサスペンドされていないか
「定期実行」タブの実行履歴で、スキップの理由を確認できます
ブラウザに古いファイルが残っている可能性があります。デプロイの完了を確認し、ページを強制再読み込みします(Mac: Cmd + Shift + R / Windows: Ctrl + Shift + R)。
静的サイトの更新は配信先へ順次反映されるため、完了後も少し時間がかかることがあります。変わらない場合は、更新先のアプリとアップロードしたファイルが合っているか、エージェントに確認を依頼します。
ワークスペースのメンバーか(招待が未承諾でないか)
ブロックされていないか
アプリの閲覧権限があるグループに入っているか
登録されたアカウントでログインしているか
IP 制御で拒否されていないか(403 画面に送信元 IP が出ます)
詳細はメンバーとロール 。
「同時に使えるアプリ数」の上限です。直近 5 分にアクセスがあったアプリと、優先起動を設定したアプリが枠を使っています。予約していない枠を使うアプリへのアクセスが途絶えてから約 5 分待つか、重要なアプリに優先起動 を設定するか、プランを上げます。
応答までに時間がかかりすぎた場合などに表示されます。Keelson では、応答開始まで 120 秒、ストリーミングを含む全体で 300 秒、ストリーミングの応答間隔で 120 秒の上限があります(HTTP の時間上限 )。
エージェントに、時間のかかっている処理を調べ、処理を短くする・結果を少しずつ返す・定期実行に分ける方法を検討してもらいます。ストリーミングでも時間上限はなくなりません。
504 が表示されても、サーバー側では保存や送信が完了している場合があります。再操作する前に結果を確認します。実装では、同じ依頼を繰り返しても重複して保存・送信しない仕組み(冪等性)が必要です。
パスが /api/webhooks/ か /api/external/ で始まっているか
/api/external/ の場合、パスが auth.endpoints に宣言され、メソッドが宣言と合っているか(/api/webhooks/ は宣言不要で、methods も適用されません)
トークンのスコープと許可 IP が合っているか
外部システムとの連携 。
シークレットは保存しただけでは、既に動いているアプリに反映されません。エージェントに反映まで依頼してください。自分で操作する場合は、コードも更新するならデプロイし、値だけを反映するならコンソールの「適用」を押します。「適用」は、コードを再アップロード・ビルドせずに再デプロイします(環境変数とシークレット )。
deploy.platform.error のようにプラットフォーム側のエラーが出た場合や、上記で解決しない場合は、お問い合わせ から連絡してください。
次を添えると、やり取りの往復が減ります。
添えるもの 取り方 ワークスペースの slug keelson workspaces list --json の slug(URL は名前の変更前のものが残る場合があります)アプリの slug keelson.yaml の slug、または keelson apps list --workspace <ワークスペース slug> --json の slugdeploy_idkeelson status --json の出力、またはコンソールの「デプロイ」タブエラーの code と message と hint CLI の出力をそのまま。--json を付けるとまとめて取れます 起きた日時とタイムゾーン ログを引くときに使います 利用者が開けない場合は、その人のメールアドレスと 403 画面に出た IP 利用者が「アクセスできません」と言う
アプリのソースコードやシークレットの値は送らないでください。必要になれば、こちらから範囲を指定して依頼します。
料金・契約・請求書についての問い合わせも同じ窓口です(料金と契約の運用 )。
ワークスペースと契約 メンバーを招待する 作ったアプリを同僚に使ってもらうときは、メールアドレスを指定してワークスペースに招待します。アプリを使うだけの人と、作成や更新も行う人で、招待時に選ぶロールが異なります。
招待は Owner または Admin が行えます。全プランで利用できます。相手が招待を受け入れ、「メンバー」画面で参加を確認できれば完了です。
アプリを作る・管理する人の人数枠を「Developers 席」と呼びます。App User はこの枠を使いません。
招待する相手 ロール Developers 席 アプリを使う人 App User 消費しない アプリを作ってデプロイする人 Developer 消費する メンバー管理も任せる人 Admin 消費する ワークスペースの共同責任者 Owner 消費する
Admin は Owner ロールで招待できません。Developer と App User は他のユーザーを招待できません。
Developer 以上のロールで招待すると、招待を出した時点で Developers 席を 1 つ確保します(相手が招待を受け入れる前でも)。席が上限に達していると、これらのロールでは招待できません。App User は席に関係なく何人でも招待できます。
コンソールの「メンバー」を開き、「メンバーを招待」を選びます
メールアドレスを入力します(1 回に最大 50 件)
ロールを選びます
「招待を送信」を選びます
招待された人に、リンク付きのメールが自動で送られます。送信直後の結果画面では、招待リンクをコピーして直接共有できます。結果画面を閉じた後にリンクが必要になった場合は、「メンバー」画面の「招待を再送」で新しいリンクを発行して共有します。
有効期限は作成から 3 日間(72 時間) です。
メールのリンクを開きます
招待されたメールアドレスと同じ Google / Microsoft アカウント、またはメールのワンタイムコードでログインします
ログインすると、招待が自動的に受け入れられます。招待されたアドレスで既にログインしている場合は、メールのリンクを開いた時点で参加します。
別のメールアドレスでログインしている場合は、招待されたアドレスでログインし直します。
参加後に使えるアプリは、アプリごとの権限 で決まります。既定では全メンバーが全アプリを使えます。
招待した人は、使ってほしいアプリの URL をチャットやメールで相手に送ります。招待メールには、アプリの URL は含まれません。
App User はコンソールでアプリの一覧や管理画面を利用できません。参加後の画面には、アプリの URL を招待した人に確認する案内が表示されます。
「メンバー」画面では、招待を受け入れる前の人は「保留中」、参加した人は「アクティブ」と表示されます。
取り消し — まだ受け入れられていない招待を無効にします
再送 — まだ受け入れられていない招待に新しいリンクを発行します。古いリンクは無効になり、有効期限は再送時から 3 日間(72 時間)です
期限切れ・取り消し済みの招待は、同じアドレスで新しく作り直します
症状 確認すること 招待が作れない Owner / Admin か。既に参加済みでないか。Developer 以上なら席が空いているか メールが届かない 迷惑メールフォルダを確認。届かなければ送信直後の結果画面でリンクをコピーして共有。画面を閉じた後は「招待を再送」で新しいリンクを発行 招待を受け入れられない 招待されたアドレスでログインしているか。期限切れ・取り消しになっていないか 参加したのにアプリが開けない アプリの閲覧権限、ログイン中のアカウント、IP 制御
自社ドメインのユーザーを招待なしで参加させるには、ドメインと参加ポリシー を設定します(Team 以上)。
グループとアプリ権限 「経理のアプリは経理チームに」「社内のお知らせは全員に」のように、アプリを使える人をグループで指定できます。アプリの更新や設定変更を行う人も、別に指定できます。
必要な権限 / プラン : グループの作成・メンバー変更は Owner / Admin。アプリの権限変更は、そのアプリの manage を持つ人。全プラン
完了条件 : 利用を許可した人のアカウントでアプリを開け、閲覧・管理のどちらの権限も持たない人のアカウントでは「アクセスできません」と表示される
目的別の手順はチームにアプリを共有する にあります。
権限 できること 閲覧(view) 実行中のアプリを開いて使う 管理(manage) アプリのデプロイ、設定変更、シークレット編集、権限の変更。閲覧も含む
権限はユーザー個人ではなくグループ に割り当てます。グループのメンバーを変えると、そのグループを割り当てたアプリの利用者・管理者も変わります。
ロール(Owner / Admin / Developer / App User)は、ワークスペースで行える操作を決めます。アプリを使えるかどうかは、上の閲覧・管理権限で決まります。ただし、IP 制御 の設定は Owner / Admin が行い、アプリの管理権限だけでは変更できません。
アプリを作ると、次が自動で割り当てられます。
グループ 権限 everyone(全メンバー)閲覧 developers(Owner / Admin / Developer)管理
つまり何もしなければ、ワークスペースの全員がアプリを使え、開発者ロールの人が管理できます。絞りたいアプリだけ変更します。
特定のグループだけに絞るときは、everyone の閲覧を外す必要があります。 「経理」グループに閲覧を足しただけでは、everyone の閲覧が残っているので全員が開けたままです。また manage には閲覧が含まれるので、管理グループ(既定では developers)のメンバーは閲覧グループに入っていなくても開けます。
「メンバー」→「グループ」で管理します。
システムグループ — ロールから自動的に決まります。編集できません。
キー メンバー ownersOwner adminsAdmin developersOwner / Admin / Developer everyone全メンバー
admins に Owner は含まれません。Owner と Admin の両方に管理を任せる場合は、owners と admins を指定します。
カスタムグループ — 「経理」「営業」「店舗スタッフ」など、業務の単位で作ります。キー(経理 のような識別子。日本語も可)は作成後に変更できません。表示名とメンバーは変更できます。アプリに割り当てられている間は削除できません。
アプリ画面の「権限」タブで、閲覧グループと管理グループを選びます。
管理グループは最低 1 つ必要です(空にはできません。メンバーがいないグループだけにもできません)
自分の管理権限を外す操作は、他の管理グループに有効なメンバーがいる場合でも確認を求められます
保存した変更は、ログイン中のユーザーも含め、通常 2 分以内に反映されます
やりたいこと 設定 全員が使える社内ツール 既定のまま 経理チームとアプリを管理する開発者が使える 閲覧: keiri、管理: developers 利用は全員、設定変更は Owner / Admin だけ 閲覧: everyone、管理: owners と admins
「上司だけが申請を承認できる」「部署ごとに見せる情報を変える」といったルールは、アプリ側に実装します。アプリを更新するための管理権限とは別に、誰がどの情報を見たり変更したりできるかを決めます。
AI エージェントには、たとえば「経理グループだけが経費の一覧を見られるようにして」と依頼します。作成後は、対象のグループの人と、それ以外の人で表示や操作を確認します。
実装では、部署などのグループは attributes.groups、アプリの管理権限は X-Keelson-User-App-Perms の manage で確認できます。詳しくは認証情報をアプリで使う を参照してください。
アプリ台帳の「アクセス範囲」に、全員に公開されていれば「全員」、限定されていれば対象の人数とグループが表示されます。
AI エージェントに設定を依頼するときは、グループに含める人と、アプリを使う人・管理する人を伝えます。次は Owner / Admin が、経理グループに閲覧を許可し、Owner / Admin に管理を任せる CLI での操作例です。
keelson groups create keiri --name "経理"
keelson access show --app my-app
keelson access set --app my-app --view keiri --manage owners --manage admins
keelson access set --app my-app --view none # 閲覧を空にする。管理権限を持つ人は利用可能
ドメインと参加ポリシー 社員が多い場合は、同じ会社のメールアドレスを持つ人が、個別の招待メールなしで参加できるようにすると便利です。社内に参加リンクを配る方法と、コンソールの「ワークスペースに参加 / 作成」画面 から申請してもらう方法があります。
設定と申請の承認は Owner または Admin が行います。Team プラン以上 で利用できます。
参加方法 メンバーになるタイミング 社内で共有された参加リンクを開く 対象のメールアドレスでログインし、「参加」を選んだとき。管理者の承認は不要 「ワークスペースに参加 / 作成」画面から申請する Owner / Admin が申請を承認したとき
どちらの方法でも、参加時のロールは App User です。Owner / Admin が後からロールを変更できます。
参加できる人は、メールアドレスの @ より後ろの部分(メールドメイン)で決まります。たとえば [email protected] のドメインは example.co.jp です。
設定する Owner / Admin と、ワークスペース作成者のメールドメインが一致している必要があります
Gmail や Outlook.com などのメールドメインでは、参加リンクを有効にできません
同じドメインを複数のワークスペースで利用できます(部署ごとのワークスペースなど)
参加リンクを有効にすると、操作した Owner / Admin のメールドメインが自動で登録されます。事前に手動で追加する必要はありません。登録内容は「設定」→「セキュリティ」→「アクセス制御」で確認できます。手動で追加する場合も、自分とワークスペース作成者のメールドメインに一致するものだけを登録できます。
「設定」→「セキュリティ」→「チーム参加リンク」を開きます
参加リンクを有効にします
URL をコピーして社内のチャットや案内ページで共有します
対象のメールアドレスを持つ人がリンクを開き、ログインして「参加」を選ぶと、その場でメンバーになります。「メンバー」画面で参加を確認できます。
参加リンクを有効にすると、対象のメールドメインでログインした人の「ワークスペースに参加 / 作成」画面 にもワークスペースが表示されます。この画面で「参加をリクエスト」を選ぶと、Owner / Admin に申請が届きます。
申請は「設定」→「セキュリティ」の「保留中の参加リクエスト」から承認または却下します。申請しただけではメンバーにならず、承認されるまでアプリにアクセスできません。
参加リンクは、ワークスペースに参加するための URL です。使ってほしいアプリの URL は別途共有します。App User にはコンソールのアプリ一覧が表示されないためです。
参加後に使えるアプリは、アプリごとの権限 で決まります。
「リセット」で現在の URL を無効にし、新しい URL を発行できます。共有先を見直したいときに使います
参加リンクを無効にすると、個別の招待で参加する方式に戻ります。既に参加したメンバーには影響しません
設定の詳細では、参加方法を「参加ポリシー」と呼びます。参加リンクの有効・無効に連動するため、ポリシーを直接選ぶ操作はありません。
ポリシー 動作 招待のみ (既定)Owner / Admin の個別の招待で参加する 参加リンク 対象のメールドメインの人は参加リンクから承認なしで参加できる。「ワークスペースに参加 / 作成」画面から申請した場合は管理者の承認が必要
IP 制御 アプリをオフィスや会社の VPN からだけ使えるようにします。利用者のログインとアプリの権限に加えて、接続元のネットワークを確認します。この仕組みを IP 制御と呼びます。
対象は、サーバー側で動く Web アプリと、画面の配信と処理を分けたハイブリッドアプリの API 部分です。静的サイト、SPA、ハイブリッドアプリの静的ファイル、Media の配信 URL には適用されません。 詳しくは適用範囲 を参照してください。
必要な権限 / プラン : アクセス元の作成、ワークスペースのデフォルト、アプリごとの設定のいずれも Owner / Admin。アプリの manage 権限だけでは変更できません。全プラン
完了条件 : 許可したネットワークからはアプリが開け、それ以外からはアクセスできない旨の画面(接続元の IP アドレスが表示される)になる
IP 制御は「アクセス元 」という単位で設定します。アクセス元は、許可するネットワークのアドレスを、名前を付けてまとめたものです。たとえば「東京オフィス」という名前で、複数の IP アドレスやアドレスの範囲を登録できます。範囲の指定には、203.0.113.0/24 のような CIDR という書き方を使います。
ワークスペースでアクセス元を作る
ワークスペースの「デフォルトで許可するアクセス元」を選ぶ(空なら IP 制限なし)
アプリごとに「ワークスペースのデフォルトを継承」か「このアプリ専用のアクセス元」かを選ぶ
新しいアプリはデフォルトを引き継ぎます。ワークスペースのデフォルトを変更すると、それを引き継ぐアプリにまとめて適用できます。専用のアクセス元を設定したアプリには、その専用設定が使われます。
コンソールの「設定」→「セキュリティ」→「アクセス元の管理」で「アクセス元を登録」を選びます。
名前 — 「福岡オフィス」「VPN」など
IP / CIDR — 1 行に 1 つ。IPv4 / IPv6 両方に対応。単一 IP(203.0.113.10)も範囲(203.0.113.0/24)も書けます。「現在の IP を追加」で自分の送信元を入れられます
ワークスペースのデフォルトに追加する — チェックすると、作成と同時にデフォルトに含まれます
登録済みのアクセス元をデフォルトに設定する場合は、同じ「セキュリティ」画面の「デフォルトで許可するアクセス元」で選び、「デフォルトを保存」を選びます。
ネットワーク管理者には「このアプリをオフィスと会社の VPN から利用できるようにしたい」と伝え、登録する固定 IP アドレスやアドレス範囲を確認します。
自宅や携帯回線では IP アドレスが変わることがあり、登録後にアクセスできなくなる場合があります。
アプリ画面の「設定」→「セキュリティ」で選びます。
モード 動作 ワークスペースのデフォルトを継承 デフォルトのアクセス元を適用する。デフォルトが空なら IP 制限なし このアプリ専用のアクセス元 デフォルトを置き換え、選んだアクセス元(1 つ以上)だけを適用する
IP 制限をかけないアプリは、空のデフォルトを引き継ぐ設定にします。デフォルトを空にすると、それを引き継ぐすべてのアプリで IP 制限が外れます。 他のアプリの制限を維持する場合は、先にそれらを「このアプリ専用のアクセス元」に切り替えてから、デフォルトを空にしてください。
設定はデプロイなしで反映されます。通常は 2 分以内に反映されます。障害中の変更は復旧後に反映されます。
許可されていないネットワークからブラウザで開くと、ログイン後に「このアプリは、許可されたアクセス元からのみ利用できます」という画面と、現在の接続元の IP アドレスが表示されます。
会社の VPN への接続が必要かを確認します。アクセス元への追加が必要な場合は、表示された IP アドレスを Owner / Admin に伝えます。
対象は、コンテナで動く Web アプリと、ハイブリッドアプリの API 部分への、ログインユーザーのアクセスです
静的サイト、SPA、ハイブリッドアプリの静的ファイル、Media の配信 URL(/__keelson/media/<ファイルID>)には適用されません 。Media ではログインとアプリの閲覧権限が確認されます(ファイルとメディア )
アプリトークンと Webhook には、ワークスペースやアプリの設定ではなく、トークンごとの許可 IP が適用されます(外部システムとの連携 )
AI クライアントから MCP 経由で呼ばれるツールにも、同じワークスペースのデフォルトとアプリごとの設定が適用されます。判定されるのは AI クライアントのサーバーの IP アドレスです。claude.ai や ChatGPT からの呼び出しは利用者の PC ではなく各社のサーバーから届くため、IP 制限のあるアプリではそのままでは拒否されます(AI クライアントから使う(MCP) )
判定は ログイン → アプリの権限 → IP の順で行われます。IP 制御は、ログインとアプリの権限確認に追加される制限です。
許可されていないネットワークからのアクセスには HTTP 403 を返します。ブラウザでページを開く場合は案内画面を、ページ内の通信(fetch / XHR)や API 呼び出しには JSON を返します。
プランと制限 プランを選ぶときや、アプリの追加・更新ができなくなったときに、利用上限を確認できます。料金は料金ページ 、プラン変更・解約・請求書などの操作は料金と契約の運用 を参照してください。
まず、次の 3 つを確認すると、必要なプランを選びやすくなります。
同時に使えるアプリ数 — 同時に利用する Web アプリの数です。保存してあるアプリの総数とは異なります
アプリを作る・管理する人数(Developers) — Owner / Admin / Developer の人数枠です。アプリを使うだけの App User は数えません
ストレージ — 保存したファイルなどの合計容量です。データベースの容量は別に扱います
Starter Plus Team 同時に使えるアプリ数 1 2 4 Developers(Owner / Admin / Developer の席) 1 2 3 バックグラウンド実行 実行回数 / 月 500 2,500 5,000 バックグラウンド実行 合計実行時間 / 月 300 分 1,500 分 5,000 分 定期実行ジョブの設定数 / アプリ 3 5 10 定期実行できる最短の間隔 60 分 15 分 5 分 バックグラウンドタスクの宣言数 / アプリ 10 10 10 1 回の実行時間の上限(定期実行・タスクの試行) 3 分 5 分 10 分 ビルド回数 / 月 100 回 300 回 1,000 回 ビルド時間 / 月 500 分 1,500 分 5,000 分 同時ビルド数 1 1 2 日次バックアップの保存数 1 世代 3 世代 7 世代 指定した時刻に復元できる期間(PITR) 24 時間 7 日 14 日 ストレージ(ワークスペース合計) 10 GB 20 GB 50 GB データベース容量(DB ごと) 固定上限なし 固定上限なし 固定上限なし メール送信の宛先数 / 月 500 2,000 10,000 優先起動(有料契約中) — ○ ○ カスタムドメイン — — 最大 10 件 メールの独自送信ドメイン — — 最大 10 件(許可アドレスはドメインごとに 20 件まで) アクセスログの閲覧範囲 30 日 90 日 180 日 アプリログの閲覧範囲 7 日 14 日 30 日
Enterprise プランは準備中です。上記を超える要件はお問い合わせ ください。
アプリを実行できる形に準備する処理を「ビルド」、決まった時刻や間隔で動かす処理を「定期実行ジョブ(cron)」、アプリが SDK で投入したときに tasks に宣言したコマンドを別のインスタンスで動かす処理を「バックグラウンドタスク」と呼びます。タスクは開始した試行 1 回(再試行を含む)をバックグラウンド実行の 1 回と数えます。バックアップの「1 世代」は、保存されたバックアップ 1 回分です。
Email SDK によるメール送信の宛先数は、To・CC・BCC の宛先 1 件を 1 と数えます。この上限はワークスペース全体の合計とアプリごとの合計の両方に適用され、どちらかに達すると送信できなくなります。
アプリの利用者数(App User)は無制限
有料プランではアプリの保存数は無制限。上限がかかるのは「同時に動かせる数」だけです。トライアル中は保有数と同時に動かせる数にそれぞれ上限があります(下の「トライアル中の制限」を参照)
認証・アクセス制御・IP 制御
日次バックアップ、手動スナップショット(1 アプリ 5 回/日)、PITR、バックアップのダウンロード
Managed SQLite(アプリ / ワークスペース単位で DB を分離)
14 日間の無料トライアル(1 アカウント 1 回)。Starter / Plus はカード登録なしで開始できます
静的サイトとしてデプロイ済みのアプリを除き、作成できるアプリは 3 個までです。未デプロイのアプリやサーバーを使うアプリはこの上限に数えます。4 個目の作成は拒否されます
同時に動かせるアプリは、プランを問わず 3 個までです。トライアル中はこの上限がプランの稼働アプリ枠となり、追加アプリのアドオンも加算されません。そのため Team は 4 個から 3 個に減ります
ビルドは直近 24 時間で 7 回までです。日付が変わっても一斉にはリセットされません
ビルドはトライアル期間の通算で 30 回までです。この 30 回は通算のため、月が変わってもリセットされません
ビルド時間と同時ビルド数は、ご契約プランの値がそのまま適用されます
有料プランへ移行すると、保有アプリ数の上限は外れ、稼働アプリ枠はプランの値と追加アプリのアドオンを合わせた数に戻ります
上限 挙動 同時に使えるアプリ数 空き枠が必要なアプリの起動・デプロイができなくなります。稼働中のアプリには影響しません。枠が空いていない状態でスリープ中のアプリにアクセスすると、起動できないことを知らせる案内ページ(HTTP 503)が表示されます。優先起動を設定していないアプリの枠は、最後のアクセスから約 5 分で解放されます Developers 開発者の席を使う招待や、新たに席を使うロール変更ができなくなります。App User の招待や、使用する席数を増やさないロール変更はできます バックグラウンド実行 実行回数 当月の残りの定期実行はスキップされ、タスクの新規投入は拒否されます(TASK_MONTHLY_QUOTA_EXCEEDED)。翌月にリセットされます バックグラウンド実行 合計実行時間 当月の残りの定期実行はスキップされ、タスクの新規投入は拒否されます(TASK_MONTHLY_QUOTA_EXCEEDED)。すでに開始した実行・試行は完了まで継続し、上限は翌月にリセットされます 定期実行ジョブの設定数・間隔・実行時間、タスクの宣言数・実行時間 keelson.yaml がプランに合わない場合、デプロイできません。AI エージェントに、表示された上限に合わせて設定の見直しを依頼しますビルド回数 / ビルド時間(月間) 新しいビルドが拒否されます。どちらの枠も翌月にリセットされます。トライアル中の通算 30 回はリセットされないため、続けるには有料プランへの移行が必要です 同時ビルド数 上限に達している間、実行中のビルドが終わるまで新しいビルドは拒否されます メール送信の宛先数 当月の残りの送信は拒否されます(MONTHLY_QUOTA_EXCEEDED)。翌月にリセットされます メールの独自送信ドメイン ドメインや許可アドレスをそれ以上追加できません。使わなくなったものを先に削除してください ストレージ すぐには停止しません。超過時はサポートから連絡します データベース容量 プランごとの固定上限はありません。ただし、基盤側の技術上限は適用されます。また、平常の業務利用を著しく超える負荷や、プラットフォームの安定運用・他のお客様の利用・当社の合理的な運用コストに影響を及ぼす利用を検知した場合、アプリの実行を制限または停止することがあります。緊急時は事前の通知なく制限することがあります
有料契約中は、必要な枠や容量を追加できます。追加の操作や請求は料金と契約の運用 を参照してください。トライアル中は追加できません。
アドオン 単位 追加ストレージ +50 GB 同時に使えるアプリ数の追加 +1 枠 追加 Developers +1 席
Web アプリが起動・利用のために確保する枠の数です。通常のアプリは、最後のアクセスから約 5 分で枠が自動的に解放されます。アクセスが続いている間は枠を使います。
スリープ中・サスペンド中のアプリは枠を消費しません
定期実行ジョブだけのアプリは枠を消費しません(Web アプリとは別に実行されます)
静的サイトは枠を消費せず、作成できる本数にも上限はありません
優先起動 を設定したアプリは、アクセスがなくても枠を常に予約します。有料契約中は Plus 以上が対象で、設定できる本数はアプリ枠の合計より 1 本少ない数までです。トライアル中は全プランで 2 本まで設定できます
起動と停止の仕組みはアプリが動くタイミング を参照してください。
アプリを作る・管理する人の人数枠を「Developers 席」と呼びます。Owner / Admin / Developer のメンバーが 1 人につき 1 席を使います。App User は数えません。
Owner / Admin / Developer の招待は、相手が受け入れる前でも、有効期限内は 1 席を予約し、使用量に含まれます。不要になった招待は取り消すと予約が外れます。
操作によって異なる席数の数え方
Owner / Admin / Developer として新しく招待するときは、これらのロールの参加済みメンバーと、有効期限内の未受諾の招待を合計して上限を判定します。招待の受諾時や、新たに開発者の席を使うロール変更では、これらのロールの参加済みメンバーだけを数えます。既に席を使っているメンバーのロール変更など、席数が増えない変更はこの上限で制限されません。
デプロイ用に保存したアプリのファイル(アーティファクト)、Files / Media SDK のファイル、スナップショットの合計容量です。ワークスペース全体で集計し、ログは含みません。Managed SQLite の容量はこの集計枠とは別に管理され、プランごとの固定上限はありません。
画面の表示やデータの保存など、アプリに送る 1 回のリクエストには時間の上限があります。長い処理がある場合は、AI エージェントに上限内で完了する処理方法を相談できます。
項目 上限 応答を開始するまで(最初のレスポンスヘッダ) 120 秒。超えるとタイムアウト(HTTP 504) 1 リクエストの合計(結果を少しずつ返すストリーミングを含む) 300 秒 ストリーミングで次のデータを返すまでの間隔(チャンク間隔) 120 秒
タイムアウトが表示されても、アプリ側では保存などの処理が完了している場合があります。AI エージェントには「同じ操作を繰り返しても、申請や注文が二重に登録されないようにして」と依頼してください。
技術的には、HTTP 504 が返ってもアプリ側の処理が取り消されたとは限りません。Keelson は POST リクエストを自動再送しませんが、利用者やクライアントが再送する可能性があります。そのため、同じリクエストを繰り返しても結果が重複しない実装が必要です。
定期実行とバックグラウンドタスクの時間上限は上のプラン別一覧、ビルドの時間上限は keelson.yaml リファレンス を参照してください。
料金と契約の運用 プランを変更したいとき、支払い方法や請求書を確認したいとき、Keelson の利用を終了したいときの手順を案内します。各プランの数値上限はプランと制限 、料金は料金ページ を参照してください。
必要な権限 : Owner または Admin。ワークスペースの削除は Owner だけ
場所 : コンソールの「設定」→「課金と使用量」。ワークスペースの削除は「設定」→「危険な操作」
各アカウントは 1 回だけ 14 日間の無料トライアルを使えます。Starter / Plus はカード登録なしで開始でき、終了までにカードを登録しなければ課金されずに自動終了 します。Team はトライアル開始時にカード登録が要ります(期間中に解約すれば課金なし)
カード登録済みの場合、トライアル終了日が初回請求日になり、以降は契約日ベースで毎月請求されます
トライアルを使い切ったアカウントが 2 つ目のワークスペースを作る場合は、決済完了と同時に課金が始まります
通貨は請求先の国で決まります(日本は JPY 税込、それ以外は USD 税抜)。初回契約で固定され、後から変えるにはサポートへの連絡が要ります
請求書払い・銀行振込は未対応です
利用者(App User)の人数は料金に影響しません。
トライアル中は、保有アプリ数・同時に動かせるアプリ数・ビルド回数に、プラン共通の上限があります。具体的な数値と数え方は、トライアル中の制限 で確認できます。
終了時の状態 起きること カード登録済み そのまま有料プランに移行し、初回請求が発生する。保有アプリ数の上限は外れ、稼働枠はプランの値に戻る カード未登録(Starter / Plus) 課金されずに自動終了する。以後、新しいデプロイ・アプリの起動・定期実行はブロックされる。アプリとデータはすぐには削除されない(解約後のアプリとデータ )
トライアル中のプラン変更は、アップグレード・ダウングレードとも直ちに適用され、料金は発生しません。
「課金と使用量」→「プラン変更」から選びます。確定前に金額が表示されます。
変更 適用 請求 アップグレード 直ちに 現在のプランの未使用期間分を差し引き、新しいプランの残り期間分を変更時に請求する。次回の請求日からは新プランの満額 ダウングレード 現在の請求期間の終わりに 日割り精算はしない。それまでは現在のプランのまま使える
ダウングレードは予約として表示され、「予約を取り消す」で切り替え前なら取り消せます。
現在の使用量が変更先の上限を超えている場合は警告が出ます。超えたまま切り替えると、次のようになります。
同時に使えるアプリ数 : スリープ中のアプリは、使用量が上限内に減るまで起動できない
Developers 席 : 上限内に収まるまで、Developer 以上のロールでの招待や、App User から Developer 以上への変更ができない
定期実行の回数 : 当月の残りはスキップされる
ストレージ : 超過してもすぐには止まらない「ソフト上限」です。デプロイ時に警告が出て、サポートから連絡します。継続的に大きく超過している場合は制限の対象になります
カスタムドメイン (Team のみ): 登録済みのものは残るが、追加・再登録ができない
「課金と使用量」→「アドオン」で、追加アプリ枠(+1)、追加 Developers 席(+1)、追加ストレージ(+50 GB)を数量で指定します。トライアル中は変更できません (トライアル終了後に追加できます)。増やした分は、残りの契約期間に応じた金額が登録済みの支払い方法へすぐに請求されます。減らした場合の差額は次回以降の請求に充当されます。
「課金と使用量」の「請求書」に最近の請求書が並び、各行から Stripe の請求書ページと PDF を開けます。
支払い方法の変更、請求先情報の編集、過去の請求書の一覧は、「課金を管理」ボタンから開く決済サービス Stripe の契約管理画面(カスタマーポータル、別タブ)で行います。ポータルで解約もできますが、Keelson のコンソールから解約する方が、終了日と影響を確認したうえで進められます。
決済に失敗した場合(支払い遅延)は、Stripe が再試行する間、サービスは通常どおり使えます。再試行が終わっても支払われないと契約が停止し、新しいデプロイ・アプリの起動・定期実行がブロックされます。「支払い方法を更新」から更新してください。
利用を終了する場合は、契約が終了するまでに、必要なデータを取り出します。 ワークスペースやアプリを削除する場合は、削除操作の前に行います。解約の申し込み後も契約終了日までは利用できるため、その間に準備できます。
データ 取り出し方 Managed SQLite のデータ コンソールのアプリ画面「復元ポイント」から、復元可能な期間内の時点を選んでダウンロード。データを書き出したファイル(SQLite の dump)を取得できます。契約終了後の猶予期間中もダウンロードできます Files SDK のファイルアプリにファイル一覧とダウンロード処理を用意し、アプリが動いているうちに取り出します Media SDK のファイルアプリに保存したファイル ID からリンクを用意し、そのアプリを閲覧できるメンバーがログインして取り出します ソースコード Git。または「デプロイ」タブの各デプロイからダウンロード 環境変数とシークレット シークレットの値はコンソールに表示されません。必要なら元の管理場所から控えます アクセスログ・アプリログ 「ログ」タブからエクスポート(アプリログは最大 5,000 行)
Files / Media には、コンソールや CLI からファイルを一覧表示・ダウンロードする機能がありません。AI エージェントには「保存したファイルを一覧から取り出せる画面を作って。Files はダウンロード処理を、Media は保存済みの ID からリンクを用意して。アプリの閲覧権限がある人だけが使えるようにして」と依頼できます。取り出したファイルが開けることも確認します。使い分けはファイルとメディア で説明しています。
契約終了後はアプリを起動できなくなるため、Files / Media の取り出しは契約終了までに済ませます。
「課金と使用量」→「プランをキャンセル」から、終了日と影響を確認し、「キャンセルを確定」を選びます。
契約終了日時(現在の請求期間の終わり)まではプランが有効なまま です。解約の申し込み後もその日時まで利用でき、残り期間分の返金もありません
契約終了日時までは「再開」でいつでも解約の申し込みを取り消せます
契約終了日時を過ぎると、新しいデプロイ・アプリの起動・定期実行がブロックされます。アプリやデータはすぐには削除されず、削除の予告と猶予期間があります
契約が終了した(解約の申し込み後に契約終了日時を過ぎた、トライアルがカード未登録で終了した)場合や、未払いで契約が停止した場合、ワークスペースのアプリは起動できなくなりますが、すぐには消えません。
対象のアプリが見つかった時点で、Owner / Admin にコンソールとメールで削除の予告 が届きます。予告には削除予定日が書かれています
一度も支払いの無いワークスペースの猶予は 3 日、支払い実績のあるワークスペースは 30 日です。猶予中も利用制限は続きますが、コンソールにログインして DB のバックアップをダウンロードできます
猶予中に契約が有効になると、予告は取り消され、アプリはそのまま残ります。契約が終了している場合は、プランを選び直して再契約します。未払いで停止している場合は、「支払い方法を更新」から未払いを解消します。アプリを残して使い続けたい場合は、この期間内に手続きを済ませます
猶予後、アプリは自動で削除されます。削除後の扱いは利用者が承認した削除と同じで、DB バックアップ・Files・秘密情報を含まない設定の記録が、通常の利用から切り離された状態で 7 日間保管されます。復元は保証されません
DB のバックアップは猶予期間中も取り出せます。Files / Media は契約終了までに取り出す必要があります(データの持ち出し )。
削除予定日は予告で確認できます。契約終了後のデータの取り扱いと、終了までのエクスポートについては、利用規約の第20条 もご確認ください。
「設定」→「危険な操作」→「このワークスペースを削除」。Owner だけが実行でき、ワークスペース名を入力して確認します。
ワークスペースとすべてのアプリが削除され、メンバーはアクセスできなくなります。コンソールから削除を取り消すことはできません
各アプリの DB バックアップ・Files・秘密情報を含まない設定の記録は、通常の利用から切り離された状態で 7 日間保管されますが、復元は保証されません
削除するとログアウトします
有効な契約がある場合、削除時に契約のキャンセル処理も行われるため、先に解約する必要はありません。ただし、キャンセル処理に失敗する場合があるため、削除後に請求が続いていないことを Stripe のポータル(削除前に「課金を管理」から開けます)または請求書メールで確認してください
Keelson のアカウント自体は、コンソール右上のアカウントメニュー →「Account settings」→「Security」の Delete account から自分で削除できます。削除されるのは Keelson のアカウントで、ログインに使っていた Google / Microsoft のアカウントは削除されません。所属していたワークスペースのアプリやデータも残ります。
リファレンス Keelson Deploy Spec Spec version: 2026-10-06 / Raw text (AI向け): /ja/docs/reference/deploy-spec.txt
この文書は、Keelson にアプリをデプロイする際の対応ランタイム・制約・成立条件を定義する正本です。デプロイの可否判断は、この文書に従ってください。
クイックスタートや操作手順は デプロイする を参照してください。
デプロイの完了は、ビルド結果だけでなく、アプリの種類に応じて確認してください。
アプリの種類 完了時に確認する条件 Web アプリ・ハイブリッド ビルドが完了し、Web アプリのプロセスが起動してヘルスチェックに通過している。アプリ URL が発行され、アクセスできる。ハイブリッドでは静的ファイルも配信できる 静的サイト・SPA 配信するファイルのアップロード・公開が完了し、アプリ URL で配信できる。アプリのプロセス起動や Web のヘルスチェックは不要 定期実行専用アプリ ビルドが完了し、定期実行のスケジュールと実行環境の設定が反映されている。Web のプロセス起動・ヘルスチェック・URL アクセスは確認対象外
Web アプリでは、ビルドが成功しても、起動に失敗した場合やヘルスチェックに通らない場合はデプロイ成功ではありません。アプリ URL は https://<ワークスペース slug>--<アプリ slug>.keelson.run です。
定期実行ジョブはデプロイ後、設定したスケジュールに従って実行されます。デプロイの成功だけでは、個々のジョブの処理が成功したことにはなりません。実行結果はジョブの履歴・ログで確認してください。
すべてのデプロイには keelson.yaml が必要です。プロジェクトのルートディレクトリに配置します。
最小構成:
db と db.mode(libsql または none)は必須です。
Flask などのフレームワークを使うアプリには本番用サーバーが必要です。本番環境向けの設定 を参照してください。
各フィールドの詳細は keelson.yaml リファレンス を参照してください。
アプリは作成時に 1 つの論理リージョンへ配置されます。リージョンの論理キーは jp-tokyo(日本)と us-oregon(米国西海岸)です。現在新規作成に開放されているのは jp-tokyo のみ で、us-oregon は定義済みですが未提供です。クラウド事業者のリージョン名ではなく、この表示名と論理キーを使います。
新規アプリでは keelson deploy --new --region <region>、または keelson.yaml のトップレベル region で配置先を指定できます。優先順位は CLI の指定、keelson.yaml、ワークスペースの既定リージョンの順です。
未提供のリージョン(現時点では us-oregon)を明示指定すると、別リージョンへ切り替えずに作成が拒否されます。指定がなければワークスペースの既定リージョン(日本)に配置されるため、ユーザーから求められない限り region は書かないでください。
リージョンはアプリ作成後に変更できません。既存アプリへ別のリージョンを指定しても移動は行われず、デプロイは拒否されます。別リージョンを使う場合は、新しいアプリとして作り直してください。
Keelson は、以下のランタイム上でのみアプリを実行できます。
ランタイム 言語 用途 python-slimPython 軽量。API、テキスト処理、自動化など python-mediaPython メディア処理向け。画像・動画ライブラリを含む node-slimNode.js 軽量。Web アプリ、API など node-mediaNode.js メディア処理向け。画像処理ライブラリを含む go-slimGo 軽量 go-mediaGo メディア処理向け
keelson.yaml の runtime フィールドで指定します。迷った場合は -slim から始め、メディア処理系ライブラリが必要になったら -media に切り替えてください。
slim — 言語ランタイムと標準ライブラリのみ。ビルドが速く、イメージサイズが小さい
media — slim に加え、画像処理(Pillow、sharp 等)や動画処理に必要なシステムライブラリがプリインストールされている
特定のフレームワークに依存しません。command で起動でき、HTTP サーバーとしてリクエストを受け付けるアプリであれば動作します。
例: FastAPI、Flask、Express、Next.js、Hono、Gin など。
以下の言語・ランタイムはサポート対象外です。
Ruby
Java / Kotlin / Scala
PHP
Rust
.NET / C#
Elixir / Erlang
Swift
非対応ランタイムを必要とする構成のままでは、Keelson へデプロイできません。
Keelson は固定されたビルド環境・実行環境を提供します。アプリはその環境上でビルドおよび起動できる必要があります。
OS: Linux
CPU: x86_64 (amd64)
アプリは非 root ユーザーとして実行されます。sudo、apt-get install、システムレベルの変更は実行できません。
リポジトリにあっても無視されます(Dockerfile があること自体はデプロイを妨げません)。Keelson はランタイムを選択し、command で起動する方式です。Dockerfile の代わりに keelson.yaml でランタイムと起動コマンドを指定します。
パス 書き込み 永続化 用途 /data不可(Keelson も作らず、アプリからも作れない) 不可 アプリは UID 1000 で実行され、root 所有の / 直下にはディレクトリを作れません アプリディレクトリ(/workspace) 直下への新規作成は不可。既存ファイルやサブディレクトリは権限によって書き込み可能 不可 ソースコード、依存関係 /tmp可(一時的) 不可 一時ファイル ホームディレクトリ(/home/appuser) Python・Node.js ランタイムでは可 不可 ランタイムやツールのキャッシュ・設定 その他 パスの所有者・権限による 不可 一時ファイルの保存には /tmp を使用
一時ファイルの書き込み先には /tmp を使用してください。ローカルファイルへの書き込みは永続化されず、再起動やインスタンスの停止で失われます
Keelson が提供する永続ストレージは 3 種類です: Managed SQLite(db.mode: libsql)、Files SDK (アプリ内部の非公開ファイル)、Media SDK (利用者に配信する画像・添付)。いずれもローカルのファイルパスとしては利用できません。外部のデータベースやストレージへの接続も可能です
ファイル SQLite は永続化されません。ファイル SQLite クライアントの使用はデプロイ時に検出され、db.local_sqlite で一時用途と宣言しない限り拒否されます
Web アプリは環境変数 PORT で指定したポートで HTTP リクエストを待ち受けてください
0.0.0.0 で listen する必要があります。127.0.0.1 や localhost ではリクエストが届きません
HTTPS 終端は Keelson が行います。アプリは HTTP で listen してください
Keelson は任意の OS パッケージ追加を前提とした環境ではありません。
-slim ランタイムには最小限のシステムライブラリのみ含まれます
-media ランタイムには画像・動画処理に必要な一般的なライブラリが含まれます
それ以外のシステムライブラリが必要な場合、アプリは動作しない可能性があります
apt-get 等によるパッケージ追加はできません(非 root のため)
command で起動した単一プロセスが基本です
systemd やデーモン管理は使えません
時刻で動く処理には crons、リクエストの後に続く処理には tasks を使ってください(バックグラウンドタスク 。workers は廃止済みで、宣言するとデプロイが拒否されます)
言語ランタイムが対応していても、依存ライブラリやシステム要件によってはデプロイできない場合があります。
以下のパッケージマネージャで管理される純粋な言語パッケージは問題なくインストールできます。
Python: pip(requirements.txt)
Node.js: npm(package.json)
Go: go mod(go.mod)
依存関係はイメージのビルド時に Keelson が自動でインストールします(requirements.txt / pyproject.toml / package.json / go.mod を検出)。command ではインストールせず、アプリの起動だけを行ってください。command に pip install / npm install / go build があると、CLI の事前チェックが command_installs_dependencies でデプロイを止めます。
ビルドの制約: Node のロックファイルは package-lock.json のみ。公開レジストリのみ(private registry・認証付きインストール不可)。Go は CGO_ENABLED=0。ビルド対象は linux/amd64。ビルド時にシークレットは渡らない。上限 600 秒。
# Go (Keelson 側で deploy 時に `./app` がビルドされます)
一部のパッケージは、C ライブラリやシステムレベルの依存を必要とします。
-media ランタイムで動作するもの: Pillow、opencv-python、sharp、ffmpeg 関連など、一般的なメディア処理ライブラリ
動作しない可能性があるもの: ランタイムに含まれないシステムライブラリに依存するパッケージ
パターン 理由 apt-get install が必要非 root でパッケージ追加不可 特殊な C ライブラリに依存 ランタイムに含まれていない可能性 GPU を前提とした推論ライブラリ GPU インスタンス未提供 データベースサーバー(PostgreSQL、MySQL、Redis) 外部サービスとして接続は可能だが、Keelson 上での起動は不可 systemd やバックグラウンドデーモン前提 プロセスモデルが異なる
デプロイモードは、command と assets の設定に応じて自動的に決まります。CLI や API に表示される deploy_mode の値とアプリの種類の対応は、次のとおりです。
アプリの種類 deploy_mode の値commandassets説明 Web アプリ containerあり なし 通常のアプリデプロイ 静的サイト edge-staticなし あり(fallback なし) 静的ファイルのみ SPA edge-spaなし あり(fallback あり) SPA(フォールバック付き) ハイブリッド hybridあり あり(type: web を明示した場合は fallback 必須) 静的ファイル + バックエンド API 定期実行専用アプリ containerなし なし crons が必須。Web サーバーを起動せず、定期実行ジョブのみを実行
定期実行専用アプリも deploy_mode は container ですが、Web アプリとは起動・完了確認の条件が異なります。
静的サイト・SPA では type: web を指定します。crons は併用できません。
アプリのホスト上には、Keelson が内部処理に使うパスや、外部からのアクセスを拒否するパスがあります。次のパスをアプリの公開エンドポイントとして使わないでください。
/__keelson とその配下は、すべての HTTP メソッドでプラットフォーム内部用 です。プラットフォームが配信するアセット・ファイルダウンロード・内部エンドポイントに使われます。これらのパスにアプリのルートを定義しないでください。
ビルド出力の配信ルート直下に __keelson ディレクトリを出力しないでください。 予約パスを含むビルドはビルド時にエラーコード reserved_path_conflict で拒否されます。ディレクトリ名を変更して再デプロイしてください。
GET /health と GET /_health は、ゲートウェイ経由ではプラットフォームが応答します。 アプリ側で同じパスを定義しても、その GET リクエストはアプリに届きません。
/api/webhooks/email と /api/webhooks/email-events は外部からアクセスできません。 エッジで拒否されるため、アプリ独自の Webhook には別のパスを使ってください。
/api/mcp と /api/mcp/ で始まるパスは、MCP のツール呼び出し専用です。 サーバー側のプログラムが動くアプリ(ハイブリッド構成のサーバー側を含む)では、keelson.yaml に mcp: を書いていなくても、MCP 経由以外のリクエストは 404 になります。このパスにはツールのハンドラ(POST /api/mcp/<ツール名>)以外のルートを置かないでください。静的に配信される部分には影響しません。
mcp.enabled: true のアプリでは、/mcp、/.well-known/oauth-protected-resource、/.well-known/oauth-protected-resource/mcp は Keelson が応答します。 これらのリクエストはアプリに届きません。詳しくは AI クライアントから使う(MCP) を参照してください。
関連ルール: auth.endpoints のパスは /__keelson で始められません(/api/external/ または /api/webhooks/ で始める必要があります)。また slug に予約語は使えません。
/assets/*(Vite の既定出力先)、/files/*、/static/*、/uploads/* などはアプリで利用できます。/api/* も、上記の例外と認証設定のルールに従って利用できます。
主要フレームワークが既定で出力する静的パスの参考一覧です。「確認済み」は本リポジトリで配信を確認したもの、「未検証」は既定パスからの推定です。未検証のフレームワークでは、実際のビルド出力と配信を確認してください。この表は /__keelson とのパス衝突の参考情報であり、フレームワークの対応可否を示すものではありません。
フレームワーク 既定の静的パス /__keelson と衝突状態 Vite(Vue / Svelte / React / Solid / Preact) /assets/*しない 確認済み Remix v2 / VitePress /assets/*しない見込み 未検証 Angular /assets/*しない見込み 未検証 Next.js /_next/static/*しない見込み 未検証 Nuxt / SvelteKit / Astro /_nuxt/* · /_app/* · /_astro/*しない見込み 未検証 CRA / Django / Flask /static/*しない見込み 未検証
アプリの起動に必要な API キー、トークン、接続情報は、コードに直接埋め込まず、環境変数またはシークレットとして設定してください。
keelson.yaml の env — バージョン管理に含めてよい値
コンソールのシークレット — API キーやトークンなど、コードに含めたくない値
必要な値が未設定の場合、アプリは正常に起動できないことがあります。
詳細は 環境変数とシークレット を参照してください。
変数名 説明 PORTアプリが listen するポート。読み取り専用で、自分で設定しない TZワークスペースのタイムゾーン。ワークスペース作成時にブラウザから自動決定される KEELSON_MODEKeelson 上で動作していることを示す印(値は keelson) KEELSON_APP_IDアプリの内部 ID KEELSON_WORKSPACE_IDワークスペースの内部 ID KEELSON_TENANT_IDKEELSON_WORKSPACE_ID の互換用別名(値は同じ)KEELSON_DEPLOY_ID現在のデプロイの内部 ID
旧 tenant 名の変数も互換のため受け付けます。撤去時期は未定です。
db.mode: libsql のときは KEELSON_DB_URL / KEELSON_DB_AUTH_TOKEN(別名 TURSO_DATABASE_URL / TURSO_AUTH_TOKEN)が追加で注入されます。KEELSON_ で始まる名前はプラットフォーム予約で、env や secrets には使えません。
Keelson のアプリは Cloud Run 上で動作し、通常運用中にも起動と停止が発生します。停止時にはプロセスへ SIGTERM が送られ、10 秒後に SIGKILL が送られます。本番用サーバーを使い、この時間内にドレイン処理を完了してください。
Flask: app.run() は Werkzeug 開発サーバーを起動します。ローカル用の __main__ エントリーポイントの中に残すことはできますが、debug=False でもデプロイ先のサーバーにしてはいけません。gunicorn を requirements.txt に追加し、次のコマンドを使います。
command : "gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 --graceful-timeout 9 app:app"
Keelson は 1 vCPU のため、worker は 1 にします。graceful timeout を 9 秒にすると、10 秒の SIGTERM 猶予内に収まります。app:app はプロジェクトのモジュール名とアプリケーションオブジェクト名に置き換えてください。
Django: gunicorn で Django を起動します。
command : "gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 --graceful-timeout 9 config.wsgi:application"
DEBUG は既定で無効にします。
DEBUG=False の場合、Django 自身は静的ファイルを配信しません。whitenoise を MIDDLEWARE に追加し、STATIC_ROOT を設定して、collectstatic 済みの成果物を配信対象に含めてください。
ALLOWED_HOSTS = ["*"] は維持してください。制限するとヘルスチェックが HTTP 400 になることがあります。
config.wsgi:application はプロジェクトの WSGI モジュールに置き換えてください。
FastAPI / uvicorn: 0.0.0.0:$PORT にバインドし、worker 数は既定の 1 のままにします。
command : "uvicorn main:app --host 0.0.0.0 --port $PORT"
--reload は使わないでください。ファイル監視がメモリを消費し、アプリが二重起動することがあります。main:app はプロジェクトのモジュール名とアプリケーションオブジェクト名に置き換えてください。
Next.js: 開発サーバーではなく、ビルド済みのアプリを起動します。
package script は次のように設定します。
"start" : "next start -p $PORT"
package.json に "start": "next dev" がある場合、回避策を加えるのではなく、その script を修正してください。next dev は本番用サーバーではありません。
Node.js: Keelson は NODE_ENV を自動設定しません。keelson.yaml で本番モードを宣言してください。未設定の場合、Express などのフレームワークがスタックトレースを返すことがあります。
Go: ビルド済みバイナリを command: "./app" で起動します。ListenAndServe を停止処理なしで放置せず、signal.NotifyContext と server.Shutdown を使って新規リクエストの受付を止め、処理中のリクエストを 10 秒の猶予内に完了させてください。
既定値は本番で安全な向きにします。Python の DEBUG は false を既定にします。
DEBUG = os.environ.get( "DEBUG" , "false" ).lower() == "true"
true を既定にしてはいけません。
DEBUG = os.environ.get( "DEBUG" , "true" ).lower() == "true"
デバッグ画面は、データベースの認証トークンを含む環境変数を表示することがあります。
Keelson が値 keelson で設定する KEELSON_MODE を使って、プラットフォーム上での実行を判別します。
ON_KEELSON = os.environ.get( "KEELSON_MODE" ) == "keelson"
本番設定の不足を即時エラーにする検査は、ON_KEELSON が true の場合だけ適用してください。DEBUG をプラットフォーム判別に使うとローカルで起動できなくなるため、代用しないでください。
対象 制限 HTTP リクエスト 120 秒以内にレスポンスを開始(超過で 504)。ストリーミングは開始後、無通信 120 秒・合計 300 秒まで 定期実行ジョブ(cron) 1〜600 秒(既定 300 秒。プラン上限がそれより低ければ切り詰め) ビルド 600 秒
アプリから外部 API やサービスへの通信はデフォルトで可能です
例外は SMTP のポート(TCP 25・465・587・2525)で、常に遮断されます。メール送信はメール配信サービスの HTTPS API を使ってください
症状 原因 対処 起動しているが接続できない、ヘルスチェックに失敗する 0.0.0.0 で listen していないhost="0.0.0.0" を明示ポートに接続できない ポート番号がハードコード 環境変数 PORT から読み取る モジュールが見つからない 依存マニフェストに記載がない、またはイメージのビルド時にインストールが失敗 ビルドログを確認し、依存を requirements.txt または package.json に記載する ネイティブモジュールのビルド失敗 システムライブラリ不足 -media ランタイムに変更、または依存を見直す起動コマンドが見つからない エントリポイントのパスが間違い ファイル名・パスを確認 事前チェックが command_installs_dependencies で止まる command に pip install / npm install がある削除して起動コマンドだけにする 検証が db 不足で止まる db.mode が無いlibsql または none を宣言するビルドが reserved_path_conflict で失敗 ビルド出力の配信ルート直下に __keelson(予約 URL プレフィックス)がある ディレクトリ名を変更する。ほかの制限対象パスは予約 URL パス を参照 定期ジョブが一度も発火しない(エラーも出ない) スケジュールがアプリのプロセス内にある(in-process スケジューラ)。予定時刻にはアプリがゼロにスケールしている crons エントリとして宣言するUI は成功と表示されたのにメール・通知が届かない レスポンスを返した後に回した処理が走っていない レスポンスを返す前に済ませるか、バックグラウンドタスク に投入する。タスクを使わない場合は、処理内容を DB に保存し、crons で定期的に読み出して実行する。次の定期実行まで待機し、実行状況によってはさらに遅れることをユーザーに伝える
ビルドログを確認 — 依存関係のインストールが成功しているか
実行ログを確認 — 起動時エラーやランタイムエラーがないか
keelson.yaml を確認 — runtime、command、env の設定が正しいか
AI エージェントは、Keelson へのデプロイ時に以下の順序で判断してください。
ランタイム確認 — アプリの言語がこの仕様の対応ランタイムに含まれるか確認する
依存関係確認 — ネイティブ依存やシステムライブラリの要件が制約内か確認する
keelson.yaml 確認 — ファイルの有無と設定内容の妥当性を確認する。なければ作成する
環境変数確認 — 必要な環境変数やシークレットが不足していないか確認する
デプロイ実行 — CLI または Skill を使ってデプロイを実行する
完了確認 — デプロイ成功の定義 に従い、アプリの種類に応じて確認する。Web アプリは起動・ヘルスチェック・URL アクセス、静的サイト・SPA は URL での配信、定期実行専用アプリは設定の反映を確認する
失敗時対応 — ログを確認し、修正可能な範囲で対処する。制約違反がある場合は理由を明示して停止する
非対応ランタイムの場合は、デプロイを試行しない。理由を明示して停止する
必須設定が不足している場合は、必要事項を提示する
ビルド成功のみで完了扱いにしない
起動失敗時は必ずログを参照する
Web 上の最新 Keelson Deploy Spec(この文書)
Web 上の最新 CLI バージョン情報
Skill 同梱版の仕様
一般知識・推測
Web 上の正本と Skill 同梱の情報が矛盾する場合は、Web 上の正本を優先してください。
keelson.yaml
keelson.yaml はプロジェクトルートに置くデプロイ設定ファイルです。ランタイム、起動コマンド、環境変数、データベース、定期実行ジョブ、静的アセットなどを定義します。
デプロイ時に Keelson はこのファイルを読み、ビルドと実行環境を決めます。入門は keelson.yaml の設定 を参照してください。
フィールド 型 必須 既定値 説明 slugstring はい — アプリの識別子。アプリ作成時に使われる workspacestring — nullプロジェクト単位の CLI 操作で使う既定ワークスペース。ワークスペースの slug を推奨。所属が 1 つだけなら CLI が自動選択するため書かなくてよい。明示した --workspace はこの値より優先し、apps list の一覧は絞り込まない descriptionstring — nullアプリの説明(300 文字以内) iconstring — nullコンソールでアプリのアイコンとして表示する画像。keelson.yaml のあるフォルダからの相対パス。icon を参照 typestring 条件付き nullアプリ種別。web のみ。起動コマンドのない静的サイト・SPA では必須 runtimestring はい — 実行環境。対応ランタイム を参照 commandstring | list 条件付き — 起動コマンド。定期実行ジョブのみ、または type: web と assets を指定した静的サイトでは省略可 envmap — {}秘密でない環境変数 dbobject はい — データベースとローカル SQLite の方針 cronslist 条件付き []定期実行ジョブ。command がなく、静的サイト(type: web と assets)でもない場合は必須 taskslist — []アプリが SDK で投入するバックグラウンドタスク。tasks を参照 mcpobject — nullAI クライアントから MCP で使うツールの宣言。mcp を参照 assetsobject — null静的アセット配信 healthobject — nullデプロイ時ヘルスチェックのパス secretsobject — {}シークレットの宣言と必須条件 authobject — null対話ログインを通さない外部向けエンドポイント verifystring | list — []デプロイ後に追加で検証するパス regionstring — null新規アプリの配置リージョン storageobject — {}廃止された disk_id だけを受理する互換ブロック
廃止されたトップレベルキー databases と workers は、値が null や空リストでも拒否されます。継続して保存する業務データは db.mode: libsql、リクエストの後に実行する処理は tasks、決まった時刻に実行する処理は crons で表現してください。
旧名のトップレベル tenant も workspace の互換用別名として受け付けます。撤去時期は
未定です。両方を書く場合、前後の空白や大文字小文字も含めて、値が完全に一致している必要があります。
上の表にないトップレベルキー(build、port、scaling など)や、各オブジェクトの中の未知のキーは拒否されます。独自のキーを足せる拡張可能な形式ではありません。crons / secrets / storage に null を書くと省略と同じにはならず拒否されます。省略したいときはキーごと書かないでください。
迷ったら、文字列の値は引用符で囲んでください。 CLI と API で同じ文字列として読み取れるようにするためです。
次のような文字列は、引用符で囲むか、ブロックスカラー(| / >)で書く必要があります。引用符なしで書くと、string_value_not_portable で拒否されます。
数字で始まる値(slug: "123-app")
日本語などの非 ASCII 文字で始まる値(description: "営業向けアプリ")
- で始まる値。コマンドの引数も対象です(command: [python, app.py, "--port", "8080"])
YAML が真偽値や null と解釈する語(yes / no / on / off / true / false / null と、env のキーの制約 に列挙した大文字小文字の表記)
: で始まる値(":memory:")など、下記の例外に当てはまらない記号で始まる値
引用符を省略できるのは、次の場合です。ただし、上に挙げた真偽値・null と解釈される語は除きます。
値の種類 引用符を省略できる書き方 例 slug、runtime、シークレット名などの識別子半角英字か _ で始まる my-app、python-slim、OPENAI_API_KEYコマンド、説明文、パスなどの文字列 半角英字か _、または /、./、../ で始まる python app.py、/health、./app
: を含むだけで引用符が必須になるわけではありません。たとえば description: https://example.com は引用符なしで書けます。ただし、: (コロンと空白)を含む文字列など、YAML 自体の構文上、引用符が必要な場合もあります。引用符を付けても、各フィールドのパス形式や文字数などの制約は変わりません。
env の値は例外で、先頭の文字にかかわらず、すべて引用符かブロックスカラーで書く必要があります(env を参照)。
アプリの識別子です。アプリ作成時の公開 URL(https://<ワークスペース slug>--<slug>.keelson.run)の一部になります。
ルール:
小文字英数字とハイフン(a-z、0-9、-)のみ
1〜63 文字
先頭と末尾は英数字
ハイフンの連続(--)は不可
予約語: admin api assets auth console health static www
public_slug は廃止された互換フィールドで、無視されます。
アプリが誰向けで何をするかを示す 1〜2 文です。
description : "営業チーム向けの日報・週報作成アプリ。週次サマリーを自動集計します"
前後の空白を除いて 300 文字(Unicode コードポイント)以内。超えるとデプロイが失敗します。コンソールのアプリ説明欄に表示され、説明がまだ空のときだけ 適用されます。コンソールで編集した説明がデプロイで上書きされることはありません。
コンソールのアプリ一覧・アプリ詳細でアプリのアイコンとして表示する画像です。省略できます。指定しないアプリは名前の頭文字で表示され、テンプレートから作ったアプリはテンプレートのアイコンで表示されます。
icon : ./assets/app-icon.png
パスは keelson.yaml のあるフォルダからの相対パスです。コマンドを実行したフォルダは関係ありません。プロジェクトの外を指すパス(絶対パス、.. で外に出るパス)、\ を含むパス、シンボリックリンクは使えません。
画像はソースと一緒にアップロードされるため、アーカイブから除外される場所には置けません(アーカイブに含まれるもの を参照)。command のない静的サイトでは assets.dir の中に置いてください。
使える画像は PNG・JPEG・WebP で、256KB 以下、縦横とも 32〜2048 ピクセルです。形式は拡張子ではなくファイルの中身で判定します。SVG は使えません。
keelson deploy(--check を含む)は、アプリを作成・アップロードする前に画像を確かめ、問題があればパスと原因を表示して止まります。原因は icon.path(見つからない・読めない・シンボリックリンク・アップロードされない)、icon.format、icon.size、icon.dimensions、icon.corrupt(画像のヘッダーが読めない)のいずれかです。
アイコンはデプロイが成功した時点で反映され、CLI は完了時に Icon: の行を 1 行表示します(--ndjson では icon_outcome)。
icon_outcome意味 appliedkeelson.yaml の画像をアプリのアイコンにしたunchangedすでに同じ画像がアイコンになっている kept_console_iconコンソールでアップロードしたアイコンを残した(keelson.yaml では置き換えない) kept_clearedコンソールでアイコンが削除されているため、デプロイでは戻さない
コンソールで設定・削除したアイコンは、常に keelson.yaml より優先されます。その後で keelson.yaml の画像を使いたい場合は、コンソールのアプリの「設定」でその画像をアップロードしてください。keelson.yaml から icon を消しても、アプリのアイコンは消えません。
アプリアイコンは順次提供中です。デプロイが icon is not available yet で拒否された場合は、keelson.yaml から icon を消して再度デプロイしてください。
アプリ種別です。起動コマンドのない静的サイト・SPA では type: web が必須です。それ以外では省略できます。
指定できる値は web だけです。type: web を指定すると、assets だけで command なしのデプロイができます。
制約:
type: web と crons は併用できません
Web アプリと定期実行ジョブを両方持つアプリでは type を省略します
実行環境です。静的サイトだけのデプロイでも必須ですが、静的サイトではビルドに使われません。静的サイトは手元や CI でビルド済みの assets.dir をそのまま配信します。
ランタイム 言語 用途 python-slimPython 軽量。API、テキスト処理など python-mediaPython 画像・動画処理(Pillow、opencv、ffmpeg 関連など) node-slimNode.js 軽量 node-mediaNode.js 画像処理(sharp など) go-slimGo 軽量 go-mediaGo メディア処理
迷ったら -slim から始め、メディア処理系ライブラリが必要になったら -media に切り替えます。
コンテナ型とハイブリッド型では、依存パッケージはビルド時に Keelson が自動でインストールします。静的サイト(type: web と assets を指定し、command なし)ではこの処理は行われません。既定でアップロードされるのは assets.dir 配下のファイルと keelson.yaml だけです(アーカイブに含まれるもの )。command には起動コマンドだけを書いてください。command に pip install / npm install / go build を含めると、CLI の事前チェックが command_installs_dependencies でデプロイを止めます。
ランタイム 検出するファイル ビルド時に実行される処理 python-*requirements.txtpython -m pip install --user -r requirements.txtpython-*pyproject.toml([project] または [build-system] あり)。requirements.txt がない場合のみpython -m pip install --user .node-*package-lock.json / package.jsonnpm ci(ロックファイルあり)または npm install、続けて npm run build --if-presentgo-*go.mod / go.sumgo mod download、go build -o /workspace/app .(command: "./app" で起動)
ビルドの制約:
requirements.txt と pyproject.toml が両方あるときは requirements.txt だけを使います。pyproject.toml 側だけに書いた依存や自作パッケージのインストールは行われないので、必要なものは requirements.txt に含めてください
インストール可能な Python の pyproject.toml には、対応するロックファイル(requirements.txt / poetry.lock / uv.lock / Pipfile.lock)のいずれかが必要です
Node.js のビルドは npm のみを使います。外部パッケージへの依存を宣言するアプリには package-lock.json が必要です。開発用・任意・peer 依存も対象です。外部依存の宣言がなければ、ロックファイルは省略できます。ロックファイルがなく、package.json がある場合は npm install が実行されます。pnpm-lock.yaml / yarn.lock だけの場合は事前チェックが lockfile_unsupported でデプロイを止めます。package-lock.json と併存している場合はそのまま残してかまいません
サードパーティ依存を宣言する Go モジュールには go.sum が必要です。標準ライブラリだけを使うモジュールには必要ありません
公開レジストリからのみ取得できます。private registry、git+ssh 依存、認証が必要なインストールは失敗します
Go は CGO_ENABLED=0 でビルドされます
ビルド対象は linux/amd64 のみ
ビルド時にシークレットは渡りません
ビルドの上限時間は 600 秒
アプリ起動時に実行するコマンドです。文字列(シェル経由)またはリスト(直接実行)で指定します。
ルール:
起動コマンド(command)、定期実行ジョブ(crons)、静的サイト(type: web と assets)のいずれかが必要です
定期実行ジョブだけのアプリに command は不要です
type: web で assets がある静的サイトに command は不要です
空文字列・空リストは「起動コマンドなし」として扱われます。通常の Web アプリでは指定が必要です。crons[].command は空にできません
依存関係のインストールは含めません(依存関係のインストール を参照)
秘密でない環境変数をキーと値で定義します。値はすべて文字列です。
PORT は Keelson が実行時に設定します。env に書いても無視されます。
値は必ず引用符で囲むか、ブロックスカラー(| / >)で書いてください。 引用符のない値は env_value_not_string で拒否され、デプロイは開始されません。数値・真偽値も同様です。
引用符が必須なのは、keelson.yaml を CLI(YAML 1.2)と API(YAML 1.1)の 2 つの実装が解析しており、引用符のないスカラーの型解決が食い違うためです。たとえば K: 0o123 は経路によって "83" にも "0o123" にもなります。引用符で囲めば両方で同じ文字列になります。
引用符を付けないキーは、英字か _ で始まり、英数字と _ だけで構成される必要があります。NODE_ENV や DB_POOL のような通常の環境変数名はそのまま書けます。
次の語は YAML 1.1 で真偽値・null と解釈されるため、引用符なしでは使えません:
yes Yes YES no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL
ハイフンを含む名前や予約語は、キーを引用符で囲みます。
KEELSON_ で始まるキー(大文字小文字を区別しない)はプラットフォーム予約で、env には設定できません。env の重複宣言、env 内のキー重複、YAML の merge key(<<)も拒否されます。
秘密の値は env ではなく secrets で宣言し、値はコンソールまたは CLI で設定します。env と同じ名前のシークレットが設定されている場合はシークレットの値が優先され、env の変更は反映されません。
データベースの扱いを選びます。db と db.mode は必須です。
フィールド 型 必須 既定値 説明 modestring はい — libsql または none。旧名 turso は libsql に正規化migratestring — nullデプロイ時に実行するマイグレーションコマンド。libsql のときのみ有効 auto_adoptboolean — false旧設定との互換のため受理されるが、現在は何もしない。DB を引き継ぐ機能ではない local_sqliteobject — null再生成可能な一時 SQLite ファイルの明示宣言
mode意味 libsqlKeelson がアプリ専用の Managed SQLite を用意し、KEELSON_DB_URL / KEELSON_DB_AUTH_TOKEN(別名 TURSO_DATABASE_URL / TURSO_AUTH_TOKEN)を注入する noneKeelson は DB を管理しない。DB 不要のアプリ、または外部 DB を使うアプリ
mode: libsql は契約も接続設定も不要で、scale-to-zero に対応します。継続して保存する業務データにはこれを推奨します。
PostgreSQL、MySQL、自前の libSQL を使う場合は mode: none にし、接続情報をシークレットで渡します。外部 DB の接続情報を Keelson が注入することはありません。
ファイル SQLite を永続化するモードはありません(/data は存在せず、アプリからも作成できません)。ファイル SQLite を使うコード(sqlite3、better-sqlite3 など)はデプロイ時に検出され、local_sqlite の宣言がなければ拒否されます。
db.migrate は、新しいイメージでトラフィックを切り替える前に 1 回だけ実行されるコマンドです。
migrate : "python migrate.py"
mode: libsql のときのみ有効。文字列で指定します
コンテナ型・ハイブリッド型でのみ実行されます。静的サイトにはコンテナがないため、宣言しても実行されません
候補リビジョンがヘルスチェックを通った後、トラフィック切り替えの前に、デプロイ対象のイメージ上で実行されます。アプリの起動コードは移行前のスキーマで動く必要があります
終了コードが 0 以外ならデプロイは deploy.runtime.migration_failed で失敗し、旧リビジョンが維持されます
毎回のデプロイで実行されるため、冪等に書きます(CREATE TABLE IF NOT EXISTS、ON CONFLICT DO NOTHING)
再生成できるキャッシュ用途のファイルだけを db.local_sqlite で宣言します。宣言してもファイルは永続化されません。
reason : "外部 API から再構築できる派生キャッシュ"
フィールド 型 必須 制約 policystring はい ephemeral のみpathslist はい 空でないこと。各パスは /tmp/ 配下か :memory: reasonstring はい 消えても問題ない理由
廃止された databases ブロックは常に拒否されます。
定期実行ジョブを定義します。各ジョブは Web サービスとは別のインスタンスで実行されます。
description : "期限切れのセッションを削除する"
command : "python cleanup.py"
フィールド 型 必須 既定値 説明 namestring はい — ジョブ名。小文字英数字とハイフン、1〜63 文字、重複不可 schedulestring はい — 5 フィールドの cron 式 commandstring | list はい — 実行コマンド timeoutinteger — 300タイムアウト秒。1〜600 enabledboolean — truefalse にするとスケジュールされないdescriptionstring — — ジョブの 1 行説明。コンソールの定期実行タブに表示する。下の crons[].description を参照
ルール:
1 アプリ最大 10 本。プランによりさらに少ない上限があります
crons[].description は表示専用です。前後の空白を除き、空なら未指定と同じです。除いた後で 100 文字を超えると cron_description_too_long で拒否されます(切り詰めはしません)。書き換えても実行内容は変わりません
type: web と併用できません
別インスタンスで実行されるため、ローカルファイル(/tmp を含む)は Web と共有されません。共有する状態は db.mode: libsql に置きます
前回の実行が継続中なら、その回はスキップされます
スケジュールはワークスペースのタイムゾーンで評価されます
timeout の絶対上限は 600 秒。省略時は 300 秒ですが、プランの上限がそれより低ければプラン上限に切り詰められます
本数・最小間隔・timeout 上限のプラン別の値はプランと制限 を参照してください。
式 意味 0 * * * *毎時 0 分 */15 * * * *15 分ごと 0 3 * * *毎日 3:00 0 9 * * 1-5平日 9:00 0 0 1 * *毎月 1 日 0:00
* * * * *(毎分)は全プランの最小間隔より短いため拒否されます。実行の挙動と設計は定期実行ジョブ を参照してください。
バックグラウンドタスクを宣言します。アプリのコードが SDK で名前を指定して投入すると、Keelson は宣言したコマンドを Web サービスとは別のインスタンスで 1 回起動し、失敗した試行は自動で再試行します。crons と違い、時刻では起動しません。投入の仕方・コマンドの書き方・2 回走っても壊れない書き方はバックグラウンドタスク を参照してください。
description : "注文の請求書 PDF を作る"
command : "python generate_pdf.py"
フィールド 型 必須 既定値 説明 namestring はい — タスク名。小文字英数字とハイフン、1〜63 文字(crons[].name と同じ規則)。前後の空白を除いて小文字化して扱うため、Foo は foo として受け付ける commandstring | list はい — 実行コマンド。文字列は /bin/sh -c、リストは直接実行 timeoutinteger — 3001 回の試行の制限時間(秒)。1〜600 max_attemptsinteger — 3初回を含む試行の最大回数。1〜5 descriptionstring — — タスクの 1 行説明。コンソールのバックグラウンドタスクタブに表示する。下の tasks[].description を参照
ルール:
1 アプリ最大 10 本(全プラン共通)
タスク名は重複できず、crons のジョブと同じ名前も使えません(task_name_conflicts_with_cron)。名前は前後の空白を除いて小文字化した後で比べます
tasks があるのに command も crons も無い設定は、タスクを投入するコードが無いため tasks_require_command_or_crons で拒否されます。type: web と assets だけで command の無い静的サイトもこれに当たります
type: web と併用できます
tasks[].description は表示専用です。前後の空白を除き、空なら未指定と同じです。除いた後で 100 文字を超えると task_description_too_long で拒否されます(切り詰めはしません)。書き換えても実行内容は変わりません
未知のキーは拒否されます。同時実行数は宣言できません(プランの値を Keelson がかけます)
timeout の絶対上限は 600 秒。明示した値がプランの上限を超えると plan_task_timeout で拒否されます。省略時の 300 秒がプランの上限より大きければ、プランの上限に切り下げます
各試行の標準入力に、attempt_no・payload・schema_version・task_id・task_name を持つ JSON が 1 行で渡されます。終了コード 0 が成功です。別インスタンスで実行されるため、ローカルファイルは Web と共有されません
timeout 上限のプラン別の値はプランと制限 を参照してください。
アプリのツールを宣言し、Claude や ChatGPT などの AI クライアントから MCP で使えるようにします。ツールが呼ばれると、Keelson がアプリの POST /api/mcp/<name> を呼びます。ログイン・同意画面・AI クライアントとのやり取りは Keelson が受け持ちます。ハンドラの書き方・接続・上限は AI クライアントから使う(MCP) を参照してください。
instructions : "Look up stock levels and record incoming deliveries."
description : "Search stock by item name."
description : "Record one incoming delivery."
required : [ item_id , quantity ]
フィールド 型 必須 既定値 説明 enabledboolean はい — true でツールを公開する。false は宣言を残したまま呼び出しを止める(既存の接続は失効しない)instructionsstring — nullAI クライアントに渡す、ツール全体の説明。4096 文字以内 toolslist 条件付き — ツールの一覧。enabled: true なら必須。書いた場合は enabled にかかわらず 1〜40 本 filestring — — instructions と tools を置く別ファイル。mcp.file を参照。新しい Keelson CLI が必要tools[].namestring はい — ツール名。^[a-z][a-z0-9_]{0,63}$(英小文字で始まり、英小文字・数字・_ だけ。小文字化などの正規化はしない)。重複不可。ハンドラのパスは POST /api/mcp/<name> tools[].descriptionstring はい — AI クライアントに見せるツールの説明。1〜1024 文字。空白だけは不可 tools[].accessstring はい — read か write。write は同意画面で別に表示され、利用者は読み取りだけを承認できるtools[].permissionstring — viewview か manage。manage のツールはアプリの管理権限を持つ人だけが使えるtools[].inputobject はい — 引数の JSON Schema(2020-12)。最上位は type: object
ルール:
宣言できるのは、サーバー側のプログラムが動くアプリ(command があり assets がない)だけです。静的サイト・SPA・ハイブリッドでは mcp is only supported for container apps で拒否されます
mcp と tools[] の未知のキーは拒否されます。ハンドラのパスは固定なので、tools[].endpoint は書けません
input は JSON として表せる値だけで書きます。入れ子は 32 段まで、JSON にして 64 KB まで。日付や、引用符なしでは文字列以外に読まれるキー(yes・on・数値など)は引用符で囲みます
input の中で $ref・$dynamicRef・$recursiveRef・x-mcp-header は使わないでください。$ref と x-mcp-header はデプロイで拒否され、$dynamicRef と $recursiveRef はデプロイを通っても呼び出しがすべて失敗します
mcp の中では YAML のアンカー・エイリアス・マージキー(<<)は使えません
mcp: を書いていなくても、サーバー側のプログラムが動くアプリでは /api/mcp と /api/mcp/ で始まるパスは MCP 専用です(予約 URL パス )
ツールが多いときは、instructions と tools を別の YAML ファイルに置けます。keelson.yaml には enabled と file だけを書きます。
# mcp.yaml(keelson.yaml と同じフォルダ)
instructions : "Look up stock levels and record incoming deliveries."
description : "Search stock by item name."
デプロイ時に Keelson CLI が別ファイルの中身を keelson.yaml の mcp に差し込んでから検査・送信します。手元の keelson.yaml は書き換えません
別ファイルのトップレベルに書けるのは instructions と tools だけです(どちらも省略可)。mcp.file と mcp.instructions / mcp.tools は同時に書けません
パスは keelson.yaml のあるフォルダからの相対パスで、そのフォルダの外(.. やシンボリックリンクで外に出る場合を含む)は指せません。拡張子は .yaml か .yml、大きさは 4 MiB まで
別ファイルの中の誤りは、mcp.yaml: tools[3].input ... のように別ファイル名と位置で示されます
mcp.file を読めるのは新しい Keelson CLI だけです。古い CLI は mcp contains unsupported field(s): file でデプロイを拒否します。keelson upgrade で CLI を最新版にしてください。CLI を通さない経路では使えません
workers(バックグラウンドワーカー)は廃止されました。トップレベルに workers があると、値が空リストや null でも workers_not_supported で拒否されます。
リクエストを受けて走らせる処理は tasks に宣言し、SDK で投入します(バックグラウンドタスク )。未処理データを定期的に処理する場合は、crons に定期実行ジョブを定義します。プランで許可される間隔で実行し、1 回ごとに未処理分を処理して終了する形にします。
command : "python worker.py"
command : "python drain.py"
静的サイト、SPA、静的ファイル + バックエンド API(ハイブリッド)の配信設定です。
フィールド 型 必須 既定値 説明 dirstring はい — アセットディレクトリ(プロジェクトルートからの相対パス) static_dirstring — nulldir の廃止された別名。両方ある場合は一致が必要fallbackstring 条件付き nullSPA 用フォールバック(例: index.html)。dir 配下の相対パス。type: web を指定したハイブリッドでは必須 apistring — null(ハイブリッドでは実効値 /api)バックエンドへ転送するパスプレフィックス。command と assets の両方があるハイブリッドで省略すると /api が使われる
ハイブリッドでは api のパス配下がバックエンドへ転送され、それ以外は静的アセットとして配信されます。省略時のプレフィックスは /api です。別のパスにしたいときだけ指定します。
ルール:
dir に .. は使えません
api は / で始まり、/ そのものではなく、/__keelson 配下でないこと
api はトップレベルの command がある場合のみ有効
type: web を指定し、assets と command の両方があるハイブリッドでは fallback が必須です。type を省略した場合、設定検証では fallback の省略が認められます。SPA の画面を配信する場合は index.html などを指定してください
静的サイト(type: web と assets を指定し、command なし)では、既定で assets.dir 配下のファイルと keelson.yaml だけをアップロードします。コンテナ型・ハイブリッド型では、ビルドに必要なソースも含めます。どちらも、以下の除外ルールが適用されます。
assets.dir: . や同じ意味の ./ は避けてください。プロジェクト直下が公開対象となり、アーカイブに含まれる全ファイルが配信される可能性があります。CLI はデプロイ前に警告しますが、この設定は禁止しません。
パスの構成要素が .git、.venv、__pycache__、.pytest_cache、node_modules、dist、build、.idea、.vscode、.DS_Store に一致するファイルやディレクトリ
ファイル名が .env で始まるか終わるファイル(.env、.env.production、.envrc、.secrets.env など)。assets.dir の中でも除外されます
シンボリックリンク、通常ファイル以外、--secrets-from-env-file で指定したファイル
宣言した assets.dir と、そこに至るまでのディレクトリは、名前による除外の対象外です。そのため、assets.dir: dist なら dist のビルド出力を含められます。ただし、その中の dist/node_modules/** などは除外されます。.git はこの例外の対象になりません。
プロジェクト固有の除外は、プロジェクト直下の .keelsonignore に書きます。.gitignore は読みません。
書き方 意味 1 行 1 パターン 一致するファイルやディレクトリを除外する。最後に一致した行が優先される # で始まる行コメント /、末尾 /、*、?、**、[abc]、[a-z]gitignore に似たパス・パターン指定 先頭 ! 一致するファイルやディレクトリを再び含める
!.env.production で env ファイルを意図的に含めることもできます。ただし、.git などの組み込み除外、.keelsonignore 自身、--secrets-from-env-file で指定したファイルは戻せません。
静的サイトで assets.dir の外側にあるファイルを含めたい場合も、先頭 ! を使います。ディレクトリとその中身を含めるには、!keep/ と !keep/** の両方が必要です。
keelson deploy --check --json を実行し、除外されたファイルと、秘密情報を含む可能性があるファイルを確認してください。
プレビュー用の認証情報やアプリ用トークンがファイル内で検出された場合は、アップロードを停止します
Webhook 署名鍵だけが検出された場合は、警告を表示して続行します
ファイル名などから秘密情報を含む可能性があると判断した場合も、警告を表示します。警告だけでは除外されないため、必要に応じて .keelsonignore に追加します
--check は主要な設定も手元で検証します。ただし、assets / crons / auth / secrets 内の未知のキー、cron 式の妥当性、verify のパス形式などは API 側で検証します。--check が通っても、デプロイ時に deploy.config.invalid で止まる場合があります。
JSON の項目 確認できる内容 archive.excluded除外されたファイル archive.excluded_env_files除外された env ファイル archive.secret_like_files名前などから秘密情報を含む可能性があると判断されたファイル archive.embedded_credentialsファイル内で検出された認証情報のパスと種別。値は表示しない archive.unscanned_filesサイズ上限などにより本文を検査しなかったファイル archive.unscanned_binary_countバイナリと判定され、本文を検査しなかったファイルの数
16 MiB を超えるファイルと、バイナリと判定されたファイルは本文を検査しません。アーカイブから除外されたファイルも検査対象外です。
secret_like_files には、credentials.json や *.pem のような名前のほか、過去に --secrets-from-env-file で指定したものの、今回は除外されていない実在ファイルも含まれます。prod-secrets.txt のように env ファイルの命名規則に当てはまらない名前も対象です。
過去に指定したファイルを判定するため、CLI はそのプロジェクト相対パスを .keelson-config/previous-secrets-files.json に保存します。この記録には秘密の値は含まれず、記録ファイル自体もアップロードから自動で除外されます。
ファイル名にコンテンツハッシュが入った JavaScript / CSS(例: index-B7hK2mQ1.js)は 1 年間キャッシュされます。Keelson は、ASCII 英数字と _ からなり英字と数字の両方を含む 8〜64 文字の末尾セグメントをハッシュと認識します。HTML、style.css や app.js のようなハッシュなしのファイル、画像などは、アクセスのたびに ETag で更新を確認します。
静的サイト(edge-static / edge-spa)の再デプロイは、新しいファイルがエッジに反映されるまで最大 60 秒ほどかかります(実測 1〜57 秒、中央値は 30 秒前後)。60 秒待ってからファイルの有無を判断してください。
デプロイ時のヘルスチェックに使うパスです。/ が重い、DB に依存する、などの場合に軽量なエンドポイントを指定します。
省略時は / を確認します
/ で始まり、.. を含まず、/__keelson で始まらない 2048 文字以内のパス
HTTP 2xx / 3xx / 404 で合格、それ以外の 4xx と 5xx で不合格。404 が通るため、合格は「起動した」ことの確認であり、そのパスが実装されていることの証明ではありません
候補リビジョンの内部 URL へ直接送られ、公開ホストや認証は経由しません。公開パスの検証は verify で行います
アプリが必要とするシークレットと、必須の組み合わせを宣言します。値はここには書かず、コンソール、CLI、またはデプロイ時の env ファイルで設定します。
description : "OpenAI API key"
- name : ANTHROPIC_API_KEY
description : "Anthropic API key"
- any_of : [ OPENAI_API_KEY , ANTHROPIC_API_KEY ]
message : "AI プロバイダのキーを少なくとも 1 つ設定してください"
フィールド 型 必須 既定値 説明 itemslist — []シークレットの定義 items[].namestring はい — 名前。環境変数の形式(大文字英字か _ で始まり、A-Z0-9_ のみ、255 文字以内)で書く。KEELSON_ で始まる名前は予約 items[].descriptionstring — ""用途の説明。コンソールに表示される requiredlist — []設定済みシークレットに対して検証するルール required[].any_oflist 条件付き nullいずれか 1 つが設定されていればよい名前の空でないリスト required[].all_oflist 条件付き nullすべて設定されている必要がある名前の空でないリスト required[].messagestring — ""未設定時に表示する案内
required の各エントリは any_of または all_of のどちらか一方だけを持ちます。参照できるのは items で宣言した名前だけです。
名前は値を設定するときに大文字に正規化され、required の照合は大文字小文字を区別します。name: api_key と書くと値は API_KEY として保存され、required の条件が満たされません。最初から大文字で書いてください。MY-KEY のようにハイフンを含む名前は宣言できても値を設定できません。
新しいアプリでは keelson deploy --new --secrets-from-env-file <path> で、アプリ作成・シークレット設定・初回デプロイを 1 回で行えます。既存アプリのシークレット変更は次のデプロイで反映されます。
Webhook の受信など、対話ログインを通さずに外部システムから呼ばれるエンドポイントを宣言します。
- path : /api/external/status
auth がある場合、endpoints は空でないリストが必須です
各エントリはパス文字列、または path と省略可能な methods を持つオブジェクト
パスは /api/external/ または /api/webhooks/ で始まり、重複しないこと。/__keelson 配下は不可
パスは前方一致 です。/api/external/status は /api/external/status-extra にも一致します
methods を指定する場合は空でないリスト。省略時は全メソッドを許可。大文字小文字は区別しません
methods が効くのは /api/external/ だけです。/api/webhooks/ には適用されず、メソッドを絞りたければアプリ側で判定します
「対話ログインを通さない」は「Keelson の認証が不要」という意味ではありません。宣言しただけでは外部から届かず、呼び出し側は Keelson が発行する資格情報を付ける必要があります。
パス 必要な資格情報 /api/external/...api スコープのアプリトークンを Authorization: Bearer で送る/api/webhooks/...webhook スコープのアプリトークンを X-Webhook-Secret ヘッダーで送るか、/api/webhooks/<secret>/... の形の URL を外部サービスに登録する
トークンの発行は keelson apps tokens create、URL の組み立ては外部連携 を参照してください。Stripe の署名だけを送る通常の Webhook や、アプリ独自の API キーだけを送るクライアントは、アプリに届く前に拒否されます。
これらのパスへのリクエストでは X-Keelson-User-Id は空文字になります(ヘッダー自体は常に付き、対話ユーザーがいなければ空)。空を「ユーザーなし」として扱ってください。Keelson の資格情報に加えて、アプリ側でも Webhook 署名や API キーによる検証を行ってください。
デプロイ後の検証で追加で確認するパスです。既定では / だけを確認します。
単一のパスは文字列でも 1 要素のリストでも指定できます
最大 20 パス(前後の空白を除き、重複を除いた数)。各パスは / で始まり、// で始まらず、パス要素としての .. と制御文字を含まないこと
コンテナ型・ハイブリッド型では公開ホスト経由で候補リビジョンから取得し、静的サイト・SPA では公開前にリリースマニフェスト上で解決します
どちらの種類でも、宣言したパスが 2xx / 3xx 以外(404 / 401 / 403 / 405 など)なら verification_declared_path_unreachable でデプロイに失敗します
verify: にはアプリ自身のログインを必要としないパスを書いてください。検証リクエストにはアプリのユーザー情報が付かないため、アプリが返す 401 / 403 も不合格です
/ は verify: にも書かれていても従来どおり寛容です。API だけのアプリが / で 404 を返しても合格します
クライアント側ルーティングでしか到達できない画面など、/ から辿れないエントリを確認したいときに使います。
これは health.path とは別の判定です。health.path は候補リビジョンを内部 URL で直接確認し、プロセスが起動した証拠として 404 でも合格します。verify は宣言した公開パスが実際に配信できるかを確認するため、404 では不合格です。
新規アプリを作るときの配置リージョンを任意で指定します。
クラウド事業者のリージョン名ではなく、Keelson の論理キーを指定します。
論理キー 表示名 新規作成 jp-tokyo日本 可(既定) us-oregon米国西海岸 未提供(指定すると拒否)
新規アプリでは CLI の --region、keelson.yaml の region、ワークスペースの既定リージョンの順で優先されます。明示したリージョンが未定義または新規作成に未開放の場合は、別リージョンへ切り替えずに拒否されます。
アプリのリージョンは作成時に確定し、後から変更できません。既存アプリと異なる region を指定したデプロイは拒否されます。別リージョンへ移す場合は、新しいアプリとして作り直してください。
storage は廃止された disk_id だけを受理します。値は無視され、永続ストレージや /data の同期を有効にしません。残っていたら削除してください。
フィールド 型 必須 既定値 説明 disk_idstring — null無視される旧識別子。小文字英数字とハイフン、1〜32 文字
デプロイモードは command、assets、assets.fallback の有無から自動的に決まります。keelson status --json などの出力では、下表の値が deploy_mode に返されます。静的サイト・SPA の設定には type: web も必要です。
呼称 deploy_modecommandassetsfallback説明 Web アプリ containerあり なし — 通常のアプリ 静的サイト edge-staticなし あり なし 静的ファイルのみ SPA edge-spaなし あり あり フォールバック付き静的ファイル ハイブリッド hybridあり あり type: web を指定した場合は必須静的ファイル + バックエンド API
ルール 内容 起動コマンド・定期実行ジョブ・静的サイトのいずれかが必要 command、crons、または type: web と assets の組み合わせを指定するタスクには投入するコードが必要 tasks がある場合は command か crons を指定する(tasks_require_command_or_crons)タスクとジョブの名前は別にする tasks[].name は crons[].name と同じにできない(task_name_conflicts_with_cron)静的サイトと定期実行ジョブは併用不可 静的サイトに必要な type: web と crons を併記すると、設定検証で拒否される。定期実行ジョブを使う場合は type を省略する 静的サイトにはコンテナがない 静的サイト・SPA では db.migrate を宣言しても実行されない。マイグレーションを使う場合はコンテナ型かハイブリッド型にする workers は廃止リクエストの後に実行する処理は tasks、決まった時刻に実行する処理は crons で書き直す db.migrate は libsql のみdb.mode: libsql が必要ローカル SQLite は一時領域のみ db.local_sqlite.paths は /tmp/ 配下か :memory:mcp はサーバー側のプログラムが動くアプリだけcommand があり assets がないアプリにだけ書ける(mcp is only supported for container apps)assets.api にはバックエンドが必要トップレベルの command を設定する type: web を指定したハイブリッドには fallback が必要type: web、assets、command を併記する場合は assets.fallback を設定する。type を省略した場合は、この必須チェックの対象外
description : "顧客と案件を管理する社内 CRM"
migrate : "python migrate.py"
手元で npm run build などを実行して dist を作ってからデプロイします。Keelson 側ではビルドしません。
command : "python report.py"
Web アプリがリクエストを受けて SDK で generate-pdf を投入し、Keelson が Web アプリとは別のインスタンスでタスクのコマンドを実行します。詳しくはバックグラウンドタスク を参照してください。
command : "python generate_pdf.py"
タスクを使わずにリクエストの後の処理を組む場合は、未処理のデータを DB に保存して定期実行ジョブで処理します。処理は次の実行まで待ちます。リクエストの後すぐに始めたい処理には、バックグラウンドタスク を使ってください。
Web アプリが未処理のデータを Managed SQLite に保存し、定期実行ジョブが別のインスタンスで処理します。両者で共有するデータは db.mode: libsql に保存します。
command : "python drain.py"
command : "node server.js"
- name : STRIPE_WEBHOOK_SECRET
description : "Stripe の Webhook 署名シークレット"
- all_of : [ STRIPE_WEBHOOK_SECRET ]
- path : /api/webhooks/stripe
Stripe に登録する URL には webhook スコープのアプリトークンを含めます(https://<host>/api/webhooks/<token>/stripe)。methods は Webhook には適用されないので、POST 以外を拒否したければアプリ側で判定します。
Keelson がデプロイ時に Linux 向けにビルドし、バイナリを ./app に置きます。
原因 対処 db または db.mode がないdb.mode を libsql か none で宣言する廃止された databases がある 削除する。永続データは Managed SQLite、一時 SQLite は db.local_sqlite で宣言 workers がある(workers_not_supported)削除する。リクエストを受けて走らせる処理は tasks、時刻で動く処理は crons で書く command に pip install / npm install がある(command_installs_dependencies)削除する。依存はビルド時に自動インストールされる 依存マニフェストがない(missing_dependency_manifest) Go ではプロジェクトルートに go.mod を置く。Python または Node.js では、外部ライブラリを使う場合に適切なマニフェストを置く。標準ライブラリだけなら不要 runtime と command の言語が合わない(runtime_command_mismatch)ランタイムを合わせるか、起動コマンドを直す env の値が引用符なし(env_value_not_string)すべての値を引用符で囲む(数値・真偽値も) 環境変数名が KEELSON_ で始まる 名前を変える。この名前空間はプラットフォーム予約 local_sqlite.paths が /tmp/ の外/tmp/、:memory:、または Managed SQLite を使う起動コマンド・定期実行ジョブ・静的サイトの設定がない command、crons、または type: web と assets の組み合わせを追加するcrons[].timeout が 600 を超える600 以下、かつプランの上限以下にする tasks があるのに command も crons も無い(tasks_require_command_or_crons)タスクを投入する Web アプリの command、または crons のジョブを追加する タスクと定期実行ジョブの名前が同じ(task_name_conflicts_with_cron) どちらかの名前を変える tasks[].timeout が 600 を超える(TASK_TIMEOUT_EXCEEDS_STANDARD_LIMIT)600 以下、かつプランの上限以下(plan_task_timeout)にするか、処理を小さなタスクに分ける mcp.enabled が true なのに mcp.tools がないツールを 1 本以上宣言するか、mcp.file で別ファイルに置く 静的サイト・SPA・ハイブリッドに mcp がある(mcp is only supported for container apps) mcp を削除するか、command だけのアプリにするmcp.tools[].input に $ref や x-mcp-header があるスキーマを展開して書く。$dynamicRef と $recursiveRef も使わない mcp contains unsupported field(s): fileKeelson CLI が古い。keelson upgrade で最新版にする assets.api が / で始まらない/api のような絶対パスにするtype: web を指定したハイブリッドで assets.fallback がないindex.html などを設定するビルドが reserved_path_conflict で失敗 ビルド出力直下の __keelson ディレクトリを改名する
環境変数一覧 Keelson がアプリのコンテナに自動設定する環境変数と、ローカル開発で Keelson SDK を使うための環境変数をまとめています。
自動設定される変数は、keelson.yaml の env に書く必要はありません。自分で定義・上書きせず、Keelson が設定した値を使います。KEELSON_ で始まる名前は Keelson が管理する予約名で、env / secrets には使えません。
変数 内容 PORTWeb アプリがリクエストを待ち受けるポート番号。起動時にこの値を読み取って使用します TZワークスペースのタイムゾーン(例: Asia/Tokyo) KEELSON_MODEKeelson 上では keelson。ローカル開発では通常は未設定。Files / Media SDK をローカル保存で使う場合や、Tasks SDK でタスクを手元で同期実行する場合は local も指定できます KEELSON_APP_IDアプリの内部 ID KEELSON_WORKSPACE_IDワークスペースの内部 ID KEELSON_TENANT_IDKEELSON_WORKSPACE_ID の互換用別名(値は同じ)KEELSON_DEPLOY_ID現在のデプロイの内部 ID KEELSON_APP_URLアプリの公開 URL(https://<ws>--<app>.keelson.run)。絶対 URL が必要な場面で使います。Keelson がアプリの公開ホスト名を生成できる場合に設定されます KEELSON_DIRECTORY_BASE_URLIdentity SDK が使う Directory API のベース URL。KEELSON_APP_URL と同じ値が、同じ条件で設定されます
既存アプリとの互換性のため、KEELSON_TENANT_ID にも KEELSON_WORKSPACE_ID と同じ値を自動設定します。旧名の廃止時期は未定です。
Files / Media / Identity / Tasks / Email SDK 用の接続先や認証情報は、各 SDK が自動で読み取ります。通常はアプリのコードから直接参照する必要はありません。
変数 条件 内容 KEELSON_DB_URLdb.mode: libsqlManaged SQLite の接続 URL KEELSON_DB_AUTH_TOKENdb.mode: libsqlManaged SQLite の認証トークン TURSO_DATABASE_URL / TURSO_AUTH_TOKENdb.mode: libsqlそれぞれ KEELSON_DB_URL / KEELSON_DB_AUTH_TOKEN と同じ値が設定される互換用の別名 KEELSON_FILES_BUCKET / KEELSON_FILES_PREFIXコンテナ型のデプロイで、ファイル保存先が構成されているとき(通常のデプロイでは自動) Files SDK が使う保存先KEELSON_INTERNAL_MEDIA_BASE_URL / KEELSON_APP_MEDIA_TOKENコンテナ型のデプロイで、Media 機能が有効なとき(通常のデプロイでは自動) Media SDK が使うアップロード先と認証トークンKEELSON_MEDIA_URL_PREFIXMedia SDK のアップロード先・認証トークンと同じ条件 Media の配信 URL の先頭部分(/__keelson/media/) KEELSON_DIRECTORY_TOKENkeelson apps directory enable を実行し、アプリを再デプロイした後Identity SDK が使う Directory API のトークン。サーバー側だけで扱います KEELSON_EMAIL_API_URL / KEELSON_EMAIL_TOKENコンテナ型のデプロイ(通常のデプロイでは自動) Email SDK がメール送信に使う接続先と認証トークン。サーバー側だけで扱いますKEELSON_EMAIL_WEBHOOK_SECRETKEELSON_EMAIL_TOKEN と同じ条件メールの配信結果 の通知の署名を検証する鍵。Email SDK の検証関数に渡しますKEELSON_TASKS_BASE_URLKeelson がバックグラウンドタスクを受け付けている間、Web・定期実行ジョブ・タスクの各コンテナに設定(tasks の宣言の有無は問いません) Tasks SDK がタスクの投入と状態の取得に使う URL。自分で設定する必要はありません
静的サイト・SPA(assets を指定し、command を省略する構成)にはコンテナがないため、実行時の環境変数は設定されません。Files / Media の SDK は静的サイトからは使えません。定期実行ジョブだけのアプリも command を省略しますが、ジョブはコンテナで動作し、SDK 用の環境変数を利用できます。
NODE_ENV — 自動では設定されません。keelson.yaml の env で "production" を宣言してください
外部 DB の接続情報 — 自動では設定されないため、シークレットで渡します。db.mode: none の場合、Managed SQLite の接続情報は自動設定されません
SDK を手元の開発環境で動かすための設定です。必要に応じてローカルの環境変数として指定し、keelson.yaml の env や Keelson のシークレットには登録しません。
変数 内容 KEELSON_MODE=localFiles / Media SDK でローカル保存を使用します。Tasks SDK では、enqueue が CLI の keelson dev task run でコマンドを手元で同期実行します。通常のローカル開発では未設定でも同じ動作になります KEELSON_FILES_DIRFiles SDK のローカル保存先(既定 ./.keelson/files) MEDIA_DIRMedia SDK のローカル保存先(既定 ./media) KEELSON_LOCAL_MODE=1Identity SDK が API に接続せず、テスト用データを返すようにします。keelson dev serve 経由で起動するときは不要です(ローカルで動かす ) KEELSON_LOCAL_USERS_FILEKEELSON_LOCAL_MODE=1 のときに Identity SDK が読む名簿ファイル(既定 ./.keelson/dev-users.json)KEELSON_LOCAL_USER_ID / KEELSON_LOCAL_USER_EMAIL / KEELSON_LOCAL_USER_NAMEローカル開発で Identity SDK が返すテスト用ユーザーの ID・メールアドレス・表示名。名簿ファイルがあるときは使いません KEELSON_LOCAL_WORKSPACE_ID / KEELSON_LOCAL_WORKSPACE_ROLE / KEELSON_LOCAL_APP_IDローカル開発で Identity SDK が返すテスト用のワークスペース ID・ワークスペース内のロール・アプリ ID
Identity SDK は、互換性のため旧名の KEELSON_LOCAL_TENANT_ID と KEELSON_LOCAL_TENANT_ROLE も読み取れます。新旧両方を指定した場合は、WORKSPACE を含む新しい名前の値が優先されます。旧名の廃止時期は未定です。
CLI コマンド keelson CLI の主なコマンドと、スクリプトやエージェントから使うときに知っておくべき挙動をまとめています。通常は AI エージェントが Skill を通じて実行するので、すべてを覚える必要はありません。各コマンドの使い方は keelson <コマンド> --help でも確認できます。
インストールはクイックスタート 、更新は keelson upgrade で行います。
以下のコマンド例では、<...> は指定する値、[...] は省略できる引数やフラグを表します。<duration> には 30s や 5m のような期間、<n> には整数を指定します。
複数のコマンドで使えるフラグです。対応状況はコマンドによって異なり、login / logout / install-agent / dev ... などでは使えるフラグが限られます。app curl は --json と --quiet を受け付けません。
フラグ 内容 --app <slug>対象アプリ。省略時はカレントディレクトリの keelson.yaml から解決。access show / access set / apps tokens create / apps tokens rotate / feedback は省略できない --workspace <slug|name|id>対象ワークスペースを slug、名前、ID のいずれかで指定する。同名のワークスペースがある場合は slug か ID を使う --json結果を JSON で出力。スクリプトやエージェントから使うときに --quiet説明や進捗を抑える。出力内容はコマンドによって異なる --timeout <duration>API 呼び出しのタイムアウト。通常は既定 15 秒。例外は下記を参照 --retry <n>一時的な失敗の再試行回数。通常は既定 0 回。例外は下記を参照 --no-browserブラウザを自動で開かず、ログイン・承認用 URL を表示する。login / apps delete / db apply / snapshots restore で使える
ワークスペースは、--workspace → keelson.yaml の workspace → 保存済みの既定ワークスペース、の順に選ばれます。ここまでで対象が決まらない場合、所属先が 1 つならそれが選ばれ、複数なら --workspace での指定が必要です。apps list は例外で、省略時は全ワークスペースを対象にします。
--quiet を付けると、secrets set はシークレット名ごとに 1 行、deploys list はデプロイ ID ごとに 1 行を出力します。deploy --check は成功時に何も出力しません。
タイムアウトと再試行回数には、次の例外があります。
apps duplicate のタイムアウトは既定 120 秒です。
app curl のアプリへのリクエストはタイムアウトが既定 130 秒で、GET / HEAD の一時的な失敗は最大 2 回再試行します。--retry 0 で再試行を無効にできます。
deploy --new のアプリ作成処理は、--retry 0 でも一時的な失敗に対して最大 3 回再試行します。この処理の再試行回数は 3 回未満に設定できません。--retry に 3 より大きい値を指定すると、その回数まで再試行します。
preview / app curl は、ブラウザでの承認が必要な場合も --no-browser を受け付けません。非対話実行ではブラウザを自動で開かず、承認用 URL を出力します。preview --json でも同様です。
--json でコマンドが失敗すると、標準出力に error オブジェクトが返ります。code はエラーコード、message は説明、hint は対処方法です。retryable が false の場合は自動再試行せず、hint に従って対処してください。
--tenant や keelson tenants list などの旧名も受け付けます。コマンドの別名 を参照してください。
コマンド 内容 keelson login [--no-browser]ブラウザでログインし、この端末を紐付ける keelson logout [--all-devices]この端末の保存済みログイン情報を削除し、サーバー側のセッションを失効させる。--all-devices ですべての端末をログアウト。KEELSON_TOKEN で渡したトークンは失効しない keelson whoamiログイン中のユーザーと、現在選ばれているワークスペース。ワークスペースの slug を確実に取るには workspaces list --json を使う keelson workspaces list [--query <text>] [--exact]所属ワークスペースの一覧・検索。--json の slug が --workspace に渡す値 keelson doctor [--fix-path]PATH・ログイン・Skill の状態を確認。--fix-path はシェルの設定ファイルに PATH を追記 keelson install-agent <claude-code|codex|cursor> [--global]AI エージェントに Skill を入れる。引数なし + --yes で入れてある Skill をすべて更新 keelson upgradeCLI を最新版に更新 keelson versionバージョン表示 keelson telemetry status|off|onCLI の利用状況データ の状態確認、停止、有効化keelson feedback --app <slug> [--deploy <id>] < feedback.jsonCLI や Skill の使い勝手を標準入力の JSON で送る。形式はフィードバック を参照
keelson install-agent の代わりに、公開リポジトリからスキルをインストールすることもできます。Claude Code では /plugin marketplace add keelsonhq/skills に続けて /plugin install keelson@keelson-skills を実行します。ほかのエージェントでは npx skills add keelsonhq/skills を使います。インストール方法はどれか 1 つだけを使ってください。組み合わせると、同じスキルが 2 つ入ったり、互いに上書きしたりすることがあります。これらの方法でインストールされるのはスキルだけなので、CLI のインストールとログイン も必要です。
Claude Code プラグインとして入れたスキルは keelson login では自動更新されず、Claude Code のプラグイン更新で追随します。プラグインは keelson doctor の検査対象外の場所にあるため、Claude Code が「not configured」と表示され、install-agent を案内されても従う必要はありません。
コマンド 内容 keelson deployカレントディレクトリのアプリをデプロイ。完了まで待つかどうかは下の表を参照 keelson deploy --new [--region <region>] [--secrets-from-env-file <path>]アプリを作成して初回デプロイ。env ファイルの値をシークレットとして登録し、そのファイルはアーカイブから除外 keelson deploy --check [--json]アップロードせず、設定の検証とアーカイブ内容(除外ファイル、秘匿値らしきファイル)を表示。ローカル検証なので、プランの上限に当たるかどうかまでは分からない keelson deploy --ndjson --yesスクリプト向け。進捗を 1 行に 1 つの JSON オブジェクトとして出力する keelson status [deploy_id] [--wait] [--max-wait <duration>]指定したデプロイの状態を表示する。ID を省略するとアプリの最新デプロイが対象になる keelson diagnose [deploy_id]ID を指定するとデプロイを診断する。省略すると稼働中アプリを診断する。起動失敗時は保存済みのアプリの起動ログも表示する keelson deploys list [--limit <n>] [--offset <n>]デプロイ履歴 keelson deploys download <deploy_id> [-o <path>]そのデプロイに使ったソースアーカイブをダウンロード(保持期間内のみ) keelson rollback [deploy_id] [--yes]前の成功デプロイ、または指定した成功デプロイに戻す
実行のしかた 挙動 対話端末で keelson deploy 完了まで待つ(既定 30 分。--watch-timeout で変更) パイプや CI など非対話で keelson deploy --yes 受け付けた時点で返る。待つなら --yes --watch --json受け付けた時点で返る。--watch と併用不可 --ndjson完了まで待つ(--no-watch と併用不可) --no-watch対話端末でも受け付けた時点で返る
通常の出力モードでは、非対話実行に --yes が必要です。省略すると confirmation_input_unavailable エラーになります。--json / --ndjson / --quiet を指定した場合は、確認を求めずに実行します。
待ち時間の上限を超えても監視をやめるだけで、サーバー側のデプロイは止まりません。status --wait で続きを確認できます。
status --wait の待機上限は既定 50 秒です。--max-wait <duration> で変更できます。上限に達すると、その時点で取得できた最後の状態を返します。デプロイが未完了でも、状態の取得に成功すれば終了コードは 0 です。
スクリプトでは、終了コードだけでデプロイの成否を判断せず、--json の terminal と status を確認してください。terminal: false なら未完了です。成功の確認には terminal: true かつ status: "completed" が必要です。
最新デプロイが失敗していても、前の成功リビジョンが動いている場合があります。現在配信しているアプリの状態は keelson app info で確認してください。
戻せる対象は、コンテナイメージを持つ成功デプロイです。静的サイトは、以前のソースを再デプロイして戻します。ロールバックではビルドを省略しますが、db.migrate は再実行されます。
rollback は受け付けた時点で戻ります。返されたデプロイ ID を keelson status <deploy_id> --wait --json に渡し、terminal と status を確認してください。--json または非対話実行では --yes が必要です。
NDJSON では、stage と status などを持つ進捗行が流れます。例えばヘルスチェック中は stage が health_check、status が progress になります。進捗行の status だけでデプロイ全体の成否を判定しないでください。
監視まで進んだ場合、最後に result を持つ行が出ます。値は success または failed です。
監視開始前に失敗した場合は、error を持つ行が出て、result 行は出ません。設定の不備などではエラー行だけですが、シークレットの登録やアーカイブのアップロード後に失敗すると、それ以前の進捗行も出ています。
プロセスの終了コードも確認してください。0 以外は CLI の処理が失敗したことを示します。監視のタイムアウトでも失敗扱いになりますが、サーバー側のデプロイは続いている場合があります。
コマンド 内容 keelson app curl <path> [-i] [--method <method>] [--data <body|@file>] [--form <name=value|name=@file>] [--header <name:value>]認証付きでアプリにリクエストを送る。デプロイ後の確認 keelson preview [--ttl <duration>] [--allow-writes] [--json]アプリへの認証付きアクセスに使う、有効期限付きのトークンを発行する keelson app info / start / stop / restartアプリの情報表示、起動、サスペンド、再起動。restart は完了まで待つ(--no-watch で受付後に返る)
app curl で --data を指定するときは、--method に POST / PUT / PATCH / DELETE のいずれかも指定してください。--form を指定し、--method を省略した場合は POST になります。複数のフォーム項目やヘッダーを指定する場合は、--form や --header を繰り返します。
レスポンス本文は標準出力に出ます。-i を付けると、HTTP ステータスとレスポンスヘッダーも標準エラー出力に表示します。GET / HEAD の一時的な失敗は既定で最大 2 回再試行し、--retry 0 で無効にできます。
preview と app curl は、現在配信しているデプロイを行った本人以外が実行すると、読み取りだけでもブラウザでの承認が必要です。この承認では、ブラウザで承認しただけではトークンの発行やリクエストの送信は行われません。承認後 30 分以内に、同じコマンドへ --confirmation <id> を付けて再実行してください。下記の「ブラウザでの承認が必要な操作」とは手順が異なります。
コマンド 内容 keelson logs app <slug> [--mode live|history] [--severity <level>] [--previous] [--limit <n>] [--since <duration>](--previous は現行ランタイムでは未対応で 422 を返す。クラッシュした旧インスタンスの出力は通常のログに含まれる)アプリの標準出力・標準エラー keelson logs cron <slug> [--severity <level>] [--limit <n>] [--since <duration>]cron の実行ログ keelson logs access [--limit <n>] [--since <duration>]アクセスログ keelson logs deploy [deploy_id] [--limit <n>] [--since <duration>]デプロイの進行ログと保存済みの失敗詳細。アプリが起動中に終了した場合は、アプリの起動ログも表示。成功時のビルド出力は保存されないため、表示できるログがなければ理由を表示
--since には 1h や 1d12h のような期間を指定します。指定できる範囲は 1 秒〜30 日です。
--json は、ログ配列などを含む 1 つの JSON オブジェクトを出力します。ログの格納先はコマンドによって異なります。
コマンド JSON 内のログ logs app / logs cronentries 配列。各要素は時刻、重大度(severity)、メッセージなどを持つオブジェクトlogs accessentries 配列。各要素は時刻、HTTP ステータス、パスなどを持つオブジェクトlogs deploylogs 配列に進行ログのオブジェクトを格納。failure_logs と startup_logs は文字列の配列
値はコマンド引数ではなく標準入力または env ファイルから渡します。
コマンド 内容 keelson secrets list設定済みの名前と更新日時。値は表示しない echo -n "<value>" | keelson secrets set <KEY> [--apply]1 件設定。--apply で再デプロイまで要求(受付後に返る) keelson secrets set --from-env-file <path> [--apply]env ファイルからまとめて設定。key ごとに保存するので、途中で失敗すると一部だけ保存された状態になる(エラーに保存済みの key が入る) keelson secrets unset <KEY>削除
シークレットは次のデプロイ(または --apply)で反映されます。
コマンド 内容 keelson apps list [--workspace <slug>] [--query <text>] [--exact]アプリ一覧。--workspace を省略すると所属する全ワークスペースを対象にする。--json の結果は、指定時は apps 配列、省略時は workspaces 配列に格納される keelson apps duplicate <slug> --name <new> [--copy-secrets] [--enable-schedule]アプリを複製。cron のスケジュールは既定で無効のまま複製 keelson apps rename <new_slug>公開 URL の slug を変える。旧 URL は 410 を返し、自動リダイレクトはされない 。反映まで時間がかかる keelson apps delete [slug]アプリを削除。ブラウザでの承認が必要 keelson quotasプランの上限と使用量
apps rename の実行後は、手元の keelson.yaml の slug も新しい値に変更してください。
複製は、元アプリの最新の成功したデプロイを基に作られます。複製先は、独自の URL とデプロイ履歴を持つ別のアプリです。
項目 複製時の扱い アプリのコード 最新の成功したデプロイから複製する 設定 (keelson.yaml) 複製先の新しいアプリ識別情報を除いて複製する 定期実行ジョブの定義 複製するが、複製先のデプロイが成功した後に停止状態で作られる。--enable-schedule を付けると有効になるが、設定で enabled: false を明示したジョブは停止状態のまま アプリ単位のシークレット 既定では複製しない。--copy-secrets を付けると複製する ワークスペース単位のシークレット 複製しないが、ワークスペース内の全アプリに渡されるため複製先でもそのまま利用できる プラットフォーム管理の資格情報 複製先用の新しい資格情報を発行する Keelson 管理 DB の中身 複製せず、新しい空の DB を作る。CLI には DB の中身を複製するオプションはない デプロイ履歴 複製しない。元アプリの最新の成功したデプロイを基に、複製先の新しいデプロイを作る
コマンド 内容 keelson crons list [--include-disabled]ジョブ一覧 keelson crons trigger <name> [--wait]今すぐ実行。--wait で実行結果まで待つ keelson crons enable <name> / disable <name>有効化 / 無効化 keelson crons runs list [--cron <name>] [--limit <n>] [--offset <n>]実行履歴 keelson dev cron run <name> [--file <path>] [--dir <path>]keelson.yaml の cron をローカルで 1 回実行するkeelson dev task run <name> [--payload <JSON> | --payload -] [--file <path>] [--dir <path>] [--json]keelson.yaml のバックグラウンドタスクをローカルで 1 回、同期で実行する(再試行なし)。--payload はタスクの payload を JSON で渡す(- で標準入力から読む。省略時は null)。--json では標準出力に結果の JSON を 1 つだけ出す。手元で enqueue したときに SDK が使うコマンド。バックグラウンドタスク を参照
コマンド 内容 keelson dev serve [--port <n>] [--users <file>] [--as <id>] -- <command...><command> でアプリのサーバーを起動し、その手前で Keelson と同じユーザー情報のヘッダーを付けて中継する。利用者は切り替えページ(/__keelson/dev)や X-Keelson-Dev-As ヘッダーで切り替える。--port は待ち受けるポート(既定 5173)、--users は名簿ファイル(既定 ./.keelson/dev-users.json、無ければ組み込みの 4 人)、--as は起動時の利用者。アプリには空いているポートを PORT で渡し、<command> 中の {port} も置き換える。デプロイ先の環境では起動しない。ローカルで動かす を参照keelson dev serve --check何も起動せずに終了コード 0 で終わる。この CLI が dev serve に対応しているかの判定に使う
コマンド 内容 keelson db apply [file.sql]Managed SQLite に SQL を実行(省略か - で標準入力)。既にテーブルなどがある DB へはブラウザでの承認が必要 。テーブル・インデックス・ビュー・トリガーを 1 つも持たない初回の DB には承認なしで適用される keelson snapshots list復元ポイントと、実行中・直近のエクスポートの一覧。エクスポートは成功・失敗したものも含む keelson snapshots create手動スナップショット keelson snapshots download <id> [-o <file>]バックアップのダウンロード。-o を省くとダウンロード URL を表示するだけでファイルは書かない keelson snapshots export --at <RFC3339>任意時点(PITR)のエクスポートを作成。完了後に download で取得 keelson snapshots restore <id>復元。ブラウザでの承認が必要 。72 時間以内なら取り消し可 keelson snapshots restore-status最新の復元の進捗と結果を確認 keelson db revoke-tokens [app] [--yes]DB の認証トークンを失効させる(破壊的)。端末内で確認を求める。非対話端末では --yes。失効後、新しいリビジョンに切り替わるまで DB は一時的に使えない keelson db recover [app] / credential-status [app]認証情報の復旧と状態
コマンド 内容 keelson groups listグループ一覧 keelson groups create <key> [--name <text>] [--description <text>] [--if-not-exists]カスタムグループを作成 keelson groups members list <key>グループのメンバー keelson groups members add|remove <key> <email>...既存メンバーの所属を変更(招待ではない) keelson access show --app <slug>アプリの閲覧 / 管理グループ keelson access set --app <slug> [--view <key>]... [--manage <key>]... [--allow-self-lockout]閲覧・管理権限を持つグループを設定する
access set は、指定した種類の権限をすべて置き換えます。--view だけを指定した場合、管理権限は変更しません。閲覧権限を空にするには --view none を指定します。管理権限は空にできません。
複数のグループを指定する場合は、フラグを繰り返してください。例えば、閲覧グループを sales と engineering に変更するには次のように実行します。
keelson access set --app my-app --view sales --view engineering
自分の管理権限が失われる変更には --allow-self-lockout が必要です。
コマンド 内容 keelson apps tokens create --app <slug> --name <name> --scope <scope> [--scope <scope>]... [--allowed-ip <cidr>]...アプリトークンを発行(1 回だけ表示)。--app は省略できない keelson apps tokens list一覧(メタデータのみ) keelson apps tokens rotate --app <slug> --token-id <id>ローテーション。旧トークンは猶予付きで失効 keelson apps tokens delete <token_id>失効 keelson apps directory enableDirectory API のトークンを発行し、KEELSON_DIRECTORY_TOKEN として登録(要再デプロイ) keelson domains listカスタムドメインの一覧と状態 keelson domains add|verify|remove <hostname> [--yes]カスタムドメインの追加・検証・削除(Team)。remove は非対話端末では --yes
--scope に指定できる値は次のとおりです。受信用と Directory 用は同じトークンに混在できません。
scope 用途 api外部システムからアプリの /api/external/... を呼ぶ webhook外部サービスからアプリの Webhook を受ける directory:members:read / directory:identity:read / directory:groups:read / directory:group-members:readアプリから Directory API を呼ぶ(通常は apps directory enable が付与する)
keelson feedback --app <slug> [--deploy <id>] < feedback.json は、CLI と Skill の使い勝手についてのフィードバックを送ります。標準入力に JSON オブジェクトを 1 つ渡します。定義されていないフィールドは拒否されます。
フィールド 内容 verdict(必須)score と summary を持つオブジェクト。score は 1〜10 の整数、summary は 1〜1,000 文字の総評。両方とも必須friction困った点を記録するオブジェクトの配列。最大 20 件。各要素のフィールドは下記を参照 yaml_confusions / error_message_reviews / wanted_commands / kept_goodそれぞれ文字列の配列。最大 20 件 skill_gaps / verification_method文字列
friction の各要素には、次の 6 フィールドがすべて必要です。
フィールド 型・内容 step文字列。困った場面や作業の段階 command文字列。実行したコマンド output_quote文字列。表示されたメッセージの引用 expected文字列。期待していた動作 lost_minutes0〜1,440 の整数。対処にかかった分数 recovered真偽値。解決できた場合は true、未解決なら false
例えば、次の内容を feedback.json に保存して送信できます。内容は実際の体験に合わせて書き換えてください。
"summary" : "デプロイできたが、非対話実行時の確認方法で迷った。"
"command" : "keelson deploy" ,
"output_quote" : "The confirmation response could not be read from standard input." ,
"expected" : "非対話実行に必要なフラグを事前に知りたかった。" ,
次の旧名も受け付けます。撤去時期は未定ですが、正式な名前のほうを使ってください。別名は --help に独立したコマンドとしては出ません。
別名 正式な名前 keelson backups list / trigger / download / restorekeelson snapshots list / create / download / restorekeelson tokens list / deletekeelson apps tokens list / deletekeelson skill install [--global] [--codex] [--yes]keelson install-agent <claude-code|codex|cursor> [--global] [--yes]keelson tenants listkeelson workspaces listkeelson db rotate-credentialskeelson db revoke-tokens--tenant--workspace
アプリの削除、既存スキーマがある DB への SQL の実行、スナップショットからの復元は、CLI だけでは完了しません。コマンドは承認用 URL を表示し(confirmation_required)、ブラウザで承認すると操作がサーバー側で実行されます。コマンドを再実行する必要はありません。承認の期限は 15 分です。
URL を表示したあとの挙動は実行のしかたで変わります。
対話端末: 既定で承認と実行の完了まで待つ。--wait=false で待たずに返る
--json または非対話端末: 既定で待たずに返る。--wait を付ければ待つ
preview / app curl の承認は、これとは別の再実行方式です(「確認」の節を参照)。rollback / db revoke-tokens / domains remove はブラウザ承認ではなく端末内の確認で、非対話端末では --yes が要ります。
変数 内容 KEELSON_TOKENログインの代わりに使うトークン(CI 向け)。保存済みログインより優先。設定してあると空文字でもエラーになる KEELSON_NO_UPDATE_CHECK=1 / KEELSON_NO_SKILL_SYNC=1更新確認 / Skill の自動更新を止める(KEELSON_NO_SKILL_SYNC は空でなければ 0 でも止まる) KEELSON_NO_TELEMETRY=1CLI の利用状況データ を止めるKEELSON_CONFIG_DIR設定ファイル(credentials.json / config.json)を置くディレクトリ KEELSON_API_BASE_URL / APP_DOMAIN_BASE接続先 API とアプリドメインの上書き(通常は不要)
エラーコードと対処方法 Keelson で発生する主なエラーと、その確認方法・対処方法をまとめています。CLI のエラーに加え、コンソールで確認できるデプロイの失敗や、公開したアプリへのアクセス時のエラーも扱います。
CLI のエラーでは code と message、対処の案内がある場合は hint を確認してください。CLI や API でデプロイの失敗を確認する場合は、failure_code と failure_hint を確認します。案内が表示されている場合は、個別の状況に応じた内容なので、このページより優先してください。AI エージェントに調査や修正を依頼するときも、これらの情報を渡すと役立ちます。
このページは全コードを網羅していません。掲載のないコードが出た場合も、表示されたメッセージや対処の案内を確認してください。
操作した場所によって、エラーを確認する画面や応答の形式が異なります。
確認する場所 確認方法・応答の形式 コンソール アプリの概要やデプロイ履歴で、失敗したデプロイの理由とログを確認 CLI ターミナルのエラーメッセージを確認。--json を付けると、標準出力の error に code、message、hint、retryable などが入る デプロイの失敗(keelson status / keelson diagnose) failure_code と failure_hint を確認Keelson API 通常は detail にメッセージ。入力検証エラーでは detail が配列になる場合もある。承認が必要な操作、スナップショット、入力検証、管理権限などに関する一部のエラーでは、error に code、message、hint などが入る 公開したアプリへのアクセス拒否(ゲートウェイ) ブラウザには案内画面。fetch / XHR には {"detail":"ip-restricted"} などの JSON。X-Keelson-Auth-Error ヘッダーで拒否の理由を確認できる 稼働枠不足・停止中(ゲートウェイ) HTTP 503。x-keelson-platform-error ヘッダーに capacity-full / app-suspended。稼働枠不足では X-Keelson-Error-Code: CAPACITY_FULL も返る 存在しない URL・停止中・予約パスへのアクセス(エッジ) HTTP 404 / 410 / 503 / 403。ブラウザには案内画面、API 等には平文を返す。一部の予約パスはブラウザにも平文を返す。理由は x-keelson-platform-error ヘッダーで確認する。ゲートウェイに届かないため X-Keelson-Auth-Error は付かない Files / Media の配信 x-keelson-error ヘッダーで理由を確認。一部のコードでは error、hint、doc を含む JSON も返る
CLI の --json で返るエラーの例です。
"message" : "Not logged in." ,
"hint" : "Run `keelson login` or set KEELSON_TOKEN, then retry the command." ,
retryable は、同じ操作を再試行すると成功する可能性があるかを示します。HTTP ステータスだけでは判断できません。同じ 503 でも false の場合があり、ビルドの 429 にはトライアルの累積上限のように待っても解除されないものがあります。
アップロード前のチェック結果です。keelson deploy --check でも確認できます。エラーがあるとデプロイは中止されます。警告だけの場合は続行できます。
依存マニフェストとは、使用するライブラリを宣言するファイル(go.mod、requirements.txt、package.json など)です。Go では外部ライブラリを使わなくても go.mod が必要です。Python と Node.js では、依存マニフェストがなくても警告にとどまります。
コード 原因 対処 missing_dependency_manifest選択したランタイムの依存マニフェストがない Go ではプロジェクトルートに go.mod を置く。Python または Node.js で外部ライブラリを使う場合は、その依存関係を宣言するファイルを置く command_installs_dependenciescommand に pip install / npm install / go build がある削除し、起動コマンドだけにする runtime_command_mismatchruntime と command の言語が合わない(例: python-slim で node)どちらかを直す assets_dir_emptyassets.dir が無い、空、またはパスの大文字小文字が違うビルドを実行する。パスを確認する assets_fallback_missingassets.fallback のファイルが assets.dir にないビルド出力を確認する db_wiring_fail(警告)db.mode とコードの DB 接続が食い違う(本番の接続先が KEELSON_DB_URL を読んでいない、ローカル開発用の file: フォールバックが本番経路に残っている、宣言との不一致など複数の規則がある。file:local.db を環境変数未設定時のフォールバックとして持つこと自体は問題ない)表示された hint に従う。多くは KEELSON_DB_URL を読む libSQL クライアントに直す file_wiring_fail(警告)状態ファイルやアップロードをローカルディスクに書いている Files / Media SDK に置き換えるicon.pathicon のファイルが無い、読めない、シンボリックリンク、またはアップロードから除外されるアップロードされる場所に画像を置き、keelson.yaml からの相対パスで icon を書く。icon を参照 icon.format / icon.size / icon.dimensions / icon.corrupticon の画像が PNG・JPEG・WebP でない、256KB を超える、縦横が 32〜2048 ピクセルの外、またはヘッダーが読めない条件に合う PNG・JPEG・WebP で書き出し直す
次のエラーがあるとデプロイできません。
コード 原因 対処 invalid_keelson_configYAML が不正、db.mode が libsql / none 以外、db.migrate を none と併用、KEELSON_ で始まる env、/__keelson 配下のパス、不明な runtime、cron が 10 本超、など message の内容を直すconfig_missing_field必須フィールドがない(slug、runtime、db など。静的サイトでは type と assets も) 追加する env_value_not_stringenv の値が文字列でない、YAML が曖昧に解釈するキー、キーの重複、merge key(<<)値は引用符かブロック文字列にする。曖昧なキー(on / yes / 数字など)は引用符で囲む。重複は削除する。merge key は展開して書く。重複と merge key は引用符で囲んでも拒否される description_too_longdescription が 300 文字超短くする workers_not_supportedworkers: がある削除する。リクエストを受けて走らせる処理は tasks、時刻で動く処理は crons で書く DB_DATABASES_REMOVEDdatabases: がある削除する。永続データは db.mode: libsql SQLITE_LOCAL_SQLITE_INVALID_PATHdb.local_sqlite.paths が /tmp/ の外/tmp/ か :memory: にするCRON_TIMEOUT_EXCEEDS_STANDARD_LIMITcrons[].timeout が 600 秒超600 秒以内にするか、処理を分割する plan_cron_limit / plan_cron_min_interval / plan_schedule_timeoutcron の本数・実行間隔・timeout がプランの制限に合わない 本数を減らす、実行間隔を長くする、timeout を短くする。または必要な条件を満たすプランに変更する tasks_require_command_or_cronstasks があるのに command も crons も無く、タスクを投入するコードが無いタスクを投入する Web アプリの command、または crons のジョブを追加する task_name_conflicts_with_crontasks[].name が crons[].name と同じ(前後の空白を除いて小文字化した後で比べる)タスクかジョブの名前を変える TASK_TIMEOUT_EXCEEDS_STANDARD_LIMITtasks[].timeout が 600 秒超600 秒以内にするか、処理を小さなタスクに分ける plan_task_timeout明示した tasks[].timeout がプランの 1 回の実行時間の上限を超える timeout を短くするか、上限の大きいプランに変更する。timeout を省略した場合は拒否されず、プランの上限に切り下げられるARTIFACT_SQLITE_FILE_DRIVERファイル SQLite クライアント(sqlite3、better-sqlite3 など)が検出された libSQL クライアントへ移行。一時用途なら db.local_sqlite で宣言
ビルド出力の直下に __keelson ディレクトリがあるとビルドが失敗します。このときの failure_code は deploy.build.failed で、ビルドログに reserved_path_conflict が出ます。ディレクトリ名を変えてください。
次のコードは警告であり、これだけでデプロイが失敗することはありません。処理の目的に応じて対応してください。
コード 原因 対処 ARTIFACT_EXEC_NODE_CRON / ARTIFACT_EXEC_APSCHEDULERアプリのプロセス内で定期処理を登録している アプリがスリープすると実行されないため、定期処理を独立したコマンドに切り出し、keelson.yaml の crons に定義する ARTIFACT_EXEC_BACKGROUND_TASKSレスポンスを返した後に実行する処理がある 短い外部呼び出しや、リクエストの成功に必要な処理は、レスポンスを返す前に await して完了を待つ。レスポンスの後に続ける処理は tasks に宣言して SDK で投入する(バックグラウンドタスク ) ARTIFACT_EXEC_SET_INTERVALサーバー側のコードで setInterval を使っている 実行が抜けても問題のないキャッシュ更新などは変更不要。継続的な定期実行が必要な処理は crons に移す
コンソールのアプリ概要・デプロイ履歴で、失敗の理由とログを確認できます。CLI の keelson status / keelson diagnose や API では、失敗コードを failure_code、対処の案内を failure_hint で確認します。デプロイ開始時に操作を受け付けられなかった場合のコードも、下表に記載しています。
コード 原因 対処 deploy.config.invalidkeelson.yaml の内容が不正指摘されたキーを直して再デプロイ deploy.config.secret_missingsecrets.required で宣言したシークレットが未設定keelson secrets set <KEY>(値は標準入力)で全て設定してから再デプロイdeploy.artifact.invalidアップロードしたアーカイブの検証に失敗した(必要なロックファイルの不足など) エラーメッセージで指摘されたファイルやコードを直す deploy.artifact.assets_invalidassets.dir / assets.fallback で宣言したファイルがアップロードに含まれていない手元でビルドしてから再デプロイ deploy.build.failedビルド失敗(依存の解決失敗、ビルドスクリプトのエラー、予約パスの衝突) keelson logs deploy <deploy_id> でビルド出力の末尾を見るdeploy.build.timed_outビルドが制限時間内に終わらなかった 不要な依存を減らす、重い前処理をビルドの外に出す deploy.build.image_too_largeイメージが大きすぎる 不要な依存やファイルを減らす deploy.runtime.start_failedアプリが起動中に終了、またはコンテナが起動状態にならなかった keelson logs deploy <deploy_id> で保存済みのアプリの起動ログを読み、PORT と 0.0.0.0 を確認deploy.runtime.health_check_failed起動・ヘルス検証の制限時間内に、/(もしくは health.path)から期待する応答(2xx / 3xx / 404)を得られなかった。アプリが起動中に終了した場合や、401 / 403 / 5xx を返し続ける場合を含む keelson logs deploy <deploy_id> で保存済みのアプリの起動ログを読み、待ち受けポートと health.path を確認deploy.runtime.migration_faileddb.migrate が 0 以外で終了。旧リビジョンが配信を継続マイグレーションを直して再デプロイ。途中まで適用された DB の変更は自動では戻らない deploy.verify.failedverify のパスが取得できない、または JS / CSS の Content-Type が不一致パスとビルド出力を確認。詳細は failure_logs の verification_* コードに出る deploy.plan.limit_exceededプランの上限を超えている failure_hint で対象の上限を確認し、設定や使用量を上限内に収める。または必要な上限のあるプランに変更するdeploy.plan.cron_count_exceededcron の本数がプラン上限を超えている cron の本数を減らすか、より多く登録できるプランに変更する deploy.plan.cron_interval_too_shortcron の間隔がプランの最小間隔より短い 実行間隔を長くするか、より短い間隔で実行できるプランに変更する deploy.plan.schedule_timeout_exceeded明示した crons[].timeout がプラン上限を超えている timeout を短くするか、必要な実行時間に対応したプランに変更するdeploy.app.suspendedアプリまたはワークスペースが Keelson 側の制限措置を受けている サポートへ連絡する。利用者や管理者による再開では解除されない deploy.app.operation_in_progressこのアプリで別の操作が進行中だったため、デプロイを開始できなかった 別の操作が完了してから再デプロイ deploy.platform.temporarily_unavailable一時的な障害 待ってから再試行する。追加で 3 回まで。それでも失敗するなら deploy_id を添えてサポートへ deploy.platform.errorプラットフォーム側のエラー 再試行しても直らない。deploy_id を添えてサポートへ deploy.cancelledデプロイが取り消された 必要なら再デプロイ deploy_in_progress(409)別のデプロイまたはアプリ操作が進行中 進行中の操作が完了してから同じコマンドを再実行 build_rate_limit_exceeded / build_guardrail_exceeded(429)ビルド回数・ビルド時間・同時実行・連続失敗の上限 メッセージが解除条件を示す。連続失敗は原因を直して記載の時刻を待つ。トライアルのビルド枠は累積で、待っても解除されない ので、その場合はプランを変更する saved_config_unsupported(409)再デプロイ / ロールバック対象の keelson.yaml が現在のスキーマに合わない 直して通常のデプロイをする
keelson crons runs list --json の executions[].failure_code で確認できます。失敗の調査には keelson logs cron で実行ログも確認してください。
cron.failed.* は開始したジョブの失敗、dispatch_failed はジョブを起動できなかったことを示します。cron.skipped.* は、条件を満たさないため予定されていた実行をスキップしたことを示します。
コード 意味 cron.failed.command_failedコマンドが 0 以外で終了した cron.failed.timed_outtimeout を超えたcron.failed.terminated_no_callback実行が終了したが結果が報告されなかった dispatch_failed実行の起動に失敗した cron.skipped.schedule_disabledジョブが無効化されている cron.skipped.quota_exceededプランの実行枠を超えた cron.skipped.due_to_lock / cron.skipped.lease_held前回の実行がまだ終わっていない cron.skipped.missed_run予定時刻を過ぎたため実行をスキップした cron.skipped.app_suspendedアプリが停止中 cron.skipped.plan_downgradeプラン変更で実行できなくなった
アプリが enqueue や get を呼んだときに、Tasks SDK が返すエラーです。SDK のエラーは言語ごとに 1 種類(Python と Node.js は TasksError、Go は *tasks.Error)で、code・status・message を持ちます。分岐は code で行い、message の文言に頼らないでください。使い方はバックグラウンドタスク を参照してください。
コード 意味 出る場面 対処 TASK_INVALID_REQUESTタスク名が空、idempotency_key が 1〜128 文字の印字可能 ASCII でない、payload を JSON にできない、などの不正な要求 enqueue(本番・手元)引数を直す。同じ呼び出しを繰り返しても通らない TASK_NOT_DECLAREDタスク名が、現在デプロイされている tasks に無い(手元では keelson.yaml に無い)。tasks から外した名前を含む enqueue(本番・手元)tasks に宣言してデプロイするか、名前を直すTASK_NOT_FOUNDtask_id が存在しないか、別のアプリのタスク。手元の get は同じプロセスで投入したタスクしか知らないget(本番・手元)アプリが保存した task_id を確かめる TASKS_UNAVAILABLEタスクの受付が閉じている、またはアプリがサスペンド・隔離・削除中。繰り返しても通らない enqueue(本番だけ)コンソールでアプリの状態を確認する。Keelson が制限したアプリはサポートに連絡する TASK_PAYLOAD_TOO_LARGE投入要求の body(payload と idempotency_key を JSON にしたもの)が 65,536 bytes を超える enqueue(本番・手元)大きな入力はデータベースかファイル保存の SDK に置き、その ID を payload で渡す TASK_BACKLOG_LIMIT_EXCEEDEDアプリの未処理(queued)のタスクが 1,000 件に達している enqueue(本番だけ)未処理のタスクが減るのを待つか、投入の頻度を下げる。投入済みのタスクには影響しない TASK_MONTHLY_QUOTA_EXCEEDEDワークスペースの月間枠「バックグラウンド実行」で、1 回目の試行の分を確保できない enqueue(本番だけ)確保済みの枠が返されたとき・プランを上げたとき・翌 UTC 月初のいずれかで通るようになる。同じ月の中でも通ることがあるので、翌月まで止まると決め打ちしない。SDK は自動で再試行しない TASKS_UNAVAILABLE_TRANSIENT一時的な障害(エラー本文の無い 502 / 503 / 504、接続の失敗、1 回あたり 15 秒の時間切れ) enqueue・get(本番だけ)SDK が合計 3 回まで試す。enqueue は idempotency_key があるときだけ再試行するので、重複を作らないようキーを付ける TASKS_UNAUTHORIZEDruntime API が ID トークンを受け付けなかった(401) enqueue・get(本番だけ)続く場合はサポートに連絡する TASKS_FORBIDDENCloud Run が呼び出しを拒否した(403)。tasks を宣言した最初のデプロイの直後は、権限の反映に数分かかることがある enqueue・get(本番だけ)最初のデプロイから数分待って試し直す。続く場合はサポートに連絡する TASKS_SERVER_ERRORエラー本文の無い、その他の 5xx enqueue・get(本番だけ)時間をおいて試し直す。enqueue を試し直すときは idempotency_key を付ける TASKS_HTTP_ERRORエラー本文の無い、その他の失敗の応答 enqueue・get(本番だけ)続く場合はサポートに連絡する TASKS_UNEXPECTED_RESPONSE成功の応答が決められた形でなかった enqueue・get(本番だけ)SDK を更新する。続く場合はサポートに連絡する TASKS_IDENTITY_TOKEN_ERRORメタデータサーバーから ID トークンを取れなかった enqueue・get(本番だけ)続く場合はサポートに連絡する TASKS_NOT_CONFIGUREDSDK が本番と手元のどちらで動かすかを決められなかった(KEELSON_MODE が不明な値、KEELSON_MODE=keelson なのに KEELSON_TASKS_BASE_URL か KEELSON_APP_ID が無い、など) enqueue・get本番では KEELSON_MODE などの KEELSON_ 変数を上書きしない。手元では KEELSON_MODE=local にするか Keelson の変数を外す。環境変数 を参照 TASKS_LOCAL_CLI_NOT_FOUNDPATH に keelson が無いenqueue(手元だけ)https://keelson.dev/install.sh で CLI を入れるTASKS_LOCAL_CLI_FAILEDCLI がタスクを実行できなかった(keelson dev task run の無い古い CLI、中断など) enqueue(手元だけ)keelson upgrade を実行する。keelson dev task run <name> --payload '<JSON>' で直接エラーを確かめる
コマンドが 0 以外で終わった・時間切れになったことは enqueue のエラーではありません。タスクは failed で終わり、get の last_failure_code に理由が入ります。
get は、failed のタスクと、再試行を待っているタスクに last_failure_code を返します。最後の試行の標準エラーは、コンソールのアプリ画面の「バックグラウンドタスク」タブで確認できます。
値 意味 試行回数に数えるか 再試行 exit_nonzeroコマンドが 0 以外の終了コードで終わった 数える 試行回数が残っていればする timed_out試行が timeout を超え、Keelson がコマンドを打ち切った 数える 試行回数が残っていればする no_completion結果の連絡が無いまま期限を過ぎた 数える 試行回数が残っていればする delivery_failed試行を 1 時間以内に開始できなかった 数えない しない manifest_unresolvable待っている間にデプロイが 2 回以上重なり、投入時の宣言を使えなくなった 数えない しない quota_exhausted再試行、または月をまたいで開始する試行で、月間枠「バックグラウンド実行」を確保できなかった 数えない しない
手動の再実行はありません。もう一度実行するには、アプリから投入し直してください。
keelson snapshots ... のエラーです。snapshot_export_ で始まるコードは、snapshots export で発生します。
コード 意味 対処 snapshot_plan_not_included手動スナップショットがプランに含まれない(現在は全プランで利用できるため、通常は発生しない) サポートに連絡する snapshot_no_managed_dbManaged SQLite を使っていない db.mode: libsql でデプロイし、DB を作成するsnapshot_db_name_invalid / snapshot_db_name_unknownDB 名が不正、または存在しない hint に出る名前を使うsnapshot_already_running / snapshot_export_already_running前の処理が実行中 終わってから再試行 snapshot_rate_limited / snapshot_export_rate_limited回数上限 hint の時刻まで待つsnapshot_export_invalid_timestamp復元可能な範囲の外の時刻 範囲内の時刻を指定する snapshot_app_deleting / snapshot_export_app_deletingアプリが削除中 — snapshot_launch_failed / snapshot_export_launch_failed起動に失敗 再試行。続くならサポートへ snapshot_disabled / snapshot_storage_unconfigured(snapshot_export_ で始まるコードも同様)機能が無効、または保存先が未設定 サポートへ連絡する snapshot_not_readyまだダウンロードできない(X-Keelson-Error-Code ヘッダー) 完了を待つ
コマンドの実行時に表示される主なコードです。
コード 意味 対処 not_logged_in未ログイン keelson loginmultiple_workspaces / workspace_ambiguous / workspace_not_foundワークスペースを特定できない --workspace <slug> で指定する。keelson workspaces list --query <検索文字列> で検索できるno_workspaces利用できるワークスペースがない コンソールでワークスペースを作成する app_not_foundアプリが見つからない slug を確認。新規なら --newapp_manage_requiredアプリは存在するが、管理権限がない 現在の管理者に、管理権限を持つグループへ自分を追加してもらう。ワークスペースの OWNER / ADMIN なら keelson groups members add <グループ> <メール> で自分を追加する app_deleting削除中のアプリ 完了を待つ forbidden権限がない。CONSOLE_ONLY_OPERATION ならコンソール限定の操作 ロール・アプリ権限を確認 confirmation_expired / confirmation_rejected承認の期限切れ(削除・SQL・復元は 15 分、preview / app curl は 30 分)/ 却下 コマンドをやり直す deploy_failedデプロイ失敗 keelson diagnose <deploy_id>sql_faileddb apply の SQL エラー。ロールバック済みSQL を直す usage(access set。API の 409 detail.reason が last_manage_binding_removed / no_effective_manager / self_lockout)管理グループが空になる、有効な管理者がいなくなる、自分の権限が失われる 管理グループを残す。--allow-self-lockout で解除できるのは自分が外れる場合だけで、管理グループや有効な管理者がゼロになる変更は解除できない transient一時的なネットワークエラー --retry 3 のように再試行回数を指定して実行
旧コードとの互換性: ワークスペースに関する一部のコードでは、旧 tenant 名のコードを互換用の error.aliases に含めます。旧コードの撤去時期は未定です。
confirmation_required は、操作を進めるためにブラウザでの承認が必要なことを示します。表示された URL を開いて承認してください。
削除・SQL・復元は承認と同時に実行されるため、コマンドの再実行は不要です。
preview / app curl は、承認後に --confirmation <id> を付けて同じコマンドを再実行してください。
meta.skill_outdated または keelson doctor の skill_outdated 警告は、インストール済みの Skill が CLI より古いことを示します。この警告だけでコマンドが失敗することはありません。keelson install-agent --yes で更新してください。
以下は公開したアプリを開いたときの案内です。コンソール自体のエラー画面ではありません。
表示 状態 対処 ログイン画面 未ログイン ワークスペースに登録されたアカウントでログイン 「このアプリへのアクセス権限がありません」(403) メンバーでない、ブロック済み、アプリの閲覧権限がない 管理者にメンバー登録・権限を依頼 「このアプリは、許可されたアクセス元からのみ利用できます」(403) IP 制御で拒否。画面に送信元 IP が表示される 管理者に、表示された IP アドレスを許可するか確認してもらう 「アプリの稼働枠が空いていないため現状アプリが起動できません。」(503) 同時に使えるアプリ数の上限 通常は、枠を使っている別のアプリへのアクセスが約 5 分途絶えると空く。枠が空かない場合は、管理者にアプリの停止やプラン変更を相談する 「アプリを起動しています」 スリープからの起動中 自動で画面が切り替わるまで待つ 「このアプリは停止されています」(503) 管理者による停止、または Keelson 側の制限措置 管理者に停止理由を確認する。管理者が再開できない場合はサポートへ連絡する 「アプリが見つかりません」(404) URL に対応するアプリが見つからない。URL の誤り、アプリの停止・削除、作成直後の公開待ちなど URL とアプリの状態を確認する。作成直後なら少し待つ 「この URL は利用できません」(410) 公開 URL が変更された(旧 URL は 30 日間予約) 管理者に現在の URL を確認する
API や XHR から同じ状況になると、ゲートウェイの拒否では JSON の detail と X-Keelson-Auth-Error ヘッダーに理由(ip-restricted、app-view-denied など)が入ります。稼働枠不足と停止中は x-keelson-platform-error ヘッダー(capacity-full、app-suspended)です。
次のエラーは、アプリへのリクエストや接続で発生します。特に WebSocket 接続の 501 は、そのままブラウザの案内画面として表示されるものではなく、利用者への表示はアプリ側のエラー処理によって異なります。
HTTP ステータス 原因 アプリ開発者の対処 504 アプリが 120 秒以内に応答ヘッダーを返し始めなかった。ストリーミング全体の時間制限ではない 応答までの処理時間を短くする。時刻や間隔を指定して実行できる定期処理なら crons に移す 501 Keelson が WebSocket に対応していない SSE やポーリングを使う
ゲートウェイで認証・認可が拒否された場合は、詳しい理由が X-Keelson-Auth-Error ヘッダーで返ります。IP 許可範囲による拒否でも、互換性のため JSON の detail は machine-forbidden または webhook-forbidden のままです。
ゲートウェイでは、アプリの経路が見つからない場合と、トークンが別のアプリのものである場合を、machine-forbidden / webhook-forbidden にまとめて返します。一方、ゲートウェイに届く前にエッジで URL の経路が見つからない場合は 404 になります。
X-Keelson-Auth-Error原因 invalid-app-tokenトークンが無効、または失効済み machine-scope-deniedトークンに api スコープがない machine-endpoint-deniedauth.endpoints で宣言されていないパス・メソッドmachine-forbidden / webhook-forbiddenゲートウェイでアプリの経路が見つからない、またはトークンが別のアプリのもの machine-ip-not-allowedアプリトークンの許可 IP の外から呼ばれた invalid-webhook-secretWebhook シークレットが一致しない webhook-scope-deniedトークンに webhook スコープがない webhook-ip-not-allowedWebhook トークンの許可 IP の外から呼ばれた
/api/webhooks/email などプラットフォーム予約のパスへの Webhook は、ゲートウェイより手前のエッジが 403 の平文で拒否します。このときのヘッダーは X-Keelson-Auth-Error ではなく x-keelson-platform-error: auth-webhook-endpoint-blocked です。
CLI の利用状況データ Keelson は、どの操作が成功しているかを把握し、信頼性の問題を見つけて CLI を改善するために、CLI の利用状況データを収集します。この機能は既定で有効です。
サブコマンド名
終了コードと、利用できる場合は公開済みの失敗符号
コマンドの所要時間
使用したフラグの名前(値は含みません)
対話端末(TTY)で実行されたかどうか
CLI のバージョン
CLI を起動したエージェントの種別(判別できない場合は不明として記録)
一覧系コマンドでは、結果が 0 件、1 件、複数のいずれかだけ
重複を除くためのイベントごとの識別子
コマンドを実行した日時
セッション識別子。端末側で作る乱数で、コマンドが 30 分記録されないと作り直されます。保存されるイベントの行には、アカウント、ワークスペース、アプリの識別子は含まれません。イベントの送信にはログイン済みの資格情報を使い、送信回数はアカウント単位で数えるため、送信経路自体は匿名ではありません。
アプリのソースコードやデプロイアーカイブの中身
ログ、標準出力、標準エラーの本文
環境変数の値やフラグに渡した値
ファイルパス、ワークスペース名、アプリ名
keelson.yaml の本文
AI エージェントとの会話
設定を保存して停止するには、次を実行します。
環境変数で停止するには、次を設定します。
環境変数は保存済みの設定より優先されます。環境変数が設定されている間は、keelson telemetry on を実行しても有効にできません。停止すると未送信のイベント記録は削除され、現在の状態はいつでも keelson telemetry status で確認できます。
停止するのはイベントの記録と送信、および X-Keelson-Client ヘッダーです。通常の User-Agent ヘッダーには、停止後も keelson-cli/<version> として CLI のバージョンが含まれます。
初めて利用状況データを送信する直前に、対話端末で実行している場合だけ 1 行の告知を表示します。対話端末ではない自動実行では表示しません。
keelson feedback は、利用者が提供するフィードバックを共有するための別の仕組みです。明示的に実行し、フィードバック共有が有効な場合にだけ送信します。フィードバック共有は既定で無効です。CLI の利用状況データを有効または無効にしても、フィードバック共有の設定は変わりません。