Telegram で 24-7 即応する秘書を Claude Code Routines(Anthropic のクラウド実行スケジュールエージェント基盤。Remote 実行=cloud routine)上に常駐させるための、迷わず動かすための手順書。claude.ai の GUI と Telegram アプリ内でほぼ完結します。
仕様の SSoT は SKILL.md、起動手順の詳細は ROUTINE_PROMPT.md、配置規約は STRUCTURE.md、ローカル動作確認は README.md。本書はそれらの上に立つ「運用開始の順路」です。
① Bot 作成 → ② chat_id 取得 → ③ プラグイン配置 → ④ 秘書人格 → ⑤ config
→ ⑥ cloud routine 登録 → ⑦ Environment 設定(GUI)→ ⑧ テスト起動
秘書の応答は親エージェント本人が起草し、本スキルは fetch / 認可 / 正規化 / 送信のみを担います。秘匿(bot token・chat_id)は cloud routine の Environment に注入し、コードやリポジトリには焼き込みません。
- Telegram アカウント
- Claude Code(cloud routine が使える環境)
- リポジトリ(最小1つ・原則 Private) — cloud routine が clone する。原則は1つの非公開リポにまとめるのが素直だが、2つに分けることもできる:
- 基本設定(
<BASE_REPO>)— 本スキルTelegramSecretary/(<BASE_REPO>内に配置、場所は任意——bootstrap が自身の位置を絶対解決)+ 本体人格Identities/<agent_name>Identity.md・SECURITY.md(cwd 起点で ROUTINE_PROMPT が読む位置)。スキルは Public 可。本体人格は公開リポへの同居も・1リポ統合で非公開側への同居も両対応——<BASE_REPO>は論理位置で、その実体が公開か非公開かは運用次第。 - 非公開データ(
<PRIVATE_DIR>)— 秘書人格SecretaryRole.mdと運用 state。Private が前提。
1つの非公開リポにまとめるのが基本(
<BASE_REPO>=<PRIVATE_DIR>、sources 1つ、cwd=リポルート)。汎用スキル等一部を公開したい場合のみ 2 分割(sources 複数、各リポ名ディレクトリ並列・cwd=親)。 - 基本設定(
- Telegram で @BotFather に話しかける
/newbot→ bot の表示名とユーザー名を決める- 返ってくる token(
123456789:ABC-DEF...の形式)を控える ← これがTELEGRAM_BOT_TOKEN
- Telegram で @userinfobot に話しかける
- 返ってくる数値 Id(例
123456789)を控える ← これがTELEGRAM_SECRETARY_AUTHORIZED_CHATS
token と chat_id は別物です。 token は bot の鍵(BotFather 発行)、chat_id はあなた個人の宛先(@userinfobot で判明)。個人 DM では
chat_id = user_id。
marketplace からインストール、または基本設定リポの TelegramSecretary/ に配置します。cloud routine は基本設定リポを fresh clone するので、TelegramSecretary/(コード一式)が基本設定リポにコミットされていることが必要です。
雛型 templates/SecretaryRole.template.md をコピーし、非公開リポの Identities/SecretaryRole.md として、秘書の固有名・対応原則・触れない話題などを定義します(人格は個人資産ゆえ非公開リポに置き、配布物には焼き込みません)。
/telegram-secretary init-config --session-duration-sec <秒> --agent-name <人格名> --private-dir <Private パス>
--session-duration-sec: 1セッションの長さ(1〜86400 秒)--agent-name: 基本設定リポのIdentities/<agent_name>Identity.mdを解決する名前--private-dir: cwd(2リポ親)起点での非公開リポのパス(例<PRIVATE_REPO>/TelegramSecretary)
config.json は基本設定リポの
TelegramSecretary/config.jsonに置き、cloud routine が fresh clone で読めるようコミットします(秘匿を含まない運用設定ゆえコミット可)。配布リポでは.gitignore対象なので、運用リポ側で明示追跡してください。
管理表(関係者・依頼・対応知・主題語彙・能力カタログ・人物理解・目標・逆算ステップ)をリポジトリに永続化する場合(任意・推奨)— cloud routine は毎回 fresh clone で起動し実行環境は揮発するため、秘書が蓄積した管理表を次回起動へ残すには、リポジトリの固定ブランチに git 永続化します。init-config では生成されないので、config.json に以下を追記します(雛型は templates/config.template.json):
{
"registry_sync": true,
"registry_dir": "ts-registry-wt",
"registry_branch": "claude/ts-registry"
}registry_sync:trueで管理表を固定ブランチへ git 永続化(更新のたび commit&push+起動時 fetch)。ローカル動作確認ではfalse(git に触れない)registry_dir: 永続管理表(individuals/tasks/knowledge/subjects/abilities/profile/goals/steps)の置き場。揮発 state(offset/lease/media)のstate_dirとは別にし、**非公開リポの独立した第二 git 作業ツリー(worktree)**を指す(bootstrap がgit worktree addで冪等 provisioning、推奨値ts-registry-wt)。dev ツリー内サブディレクトリにすると起動時 fetch のcheckout -Bが親リポを破壊するため不可(→ DESIGN §3.6)。未設定ならstate_dirにフォールバックregistry_branch: push 先の固定ブランチ(既定claude/ts-registry)。registry_remote(既定origin)と組で運用。揮発 state と分けることで「消えてよいもの」と「蓄積が本質のもの」を物理分離します
/telegram-secretary schedule
- routine 本体(cron+prompt body+sources)を作成します
- sources は基本設定+非公開(分けるなら2つ、1リポにまとめるなら1つ)
- prompt body 内の
<BASE_REPO>/<PRIVATE_DIR>は schedule が自動で実リポ名に置換します(手置換不要) registry_syncを有効にした場合、管理表はregistry_dir(独立 worktree)からregistry_cliが固定ブランチregistry_branch(既定claude/ts-registry)へ直接 push します(bootstrap.shが worktree を provisioning、認証は cloud routine の git credential。DESIGN §3.6)。routine のoutcomesへのregistry_branch名指し宣言は不要です(2026-06-05 worktree 移行後)
environment_idは後から差し替え可能です。先に routine を作っておき、次の ⑦ で環境を整えてから紐付ける流れが、一般には迷いにくくおすすめです。
claude.ai の Code → Environments で:
- 環境変数:
TELEGRAM_BOT_TOKEN= ① の tokenTELEGRAM_SECRETARY_AUTHORIZED_CHATS=[② の chat_id](JSON 整数配列。例[123456789])
- network policy(egress 許可):
api.telegram.orgを許可 ← これが無いと起動時にhost_not_allowedで止まります - 作成した Environment を routine に紐付け(GUI、または
/telegram-secretary scheduleの再実行でenvironment_idを指定)
- 手動起動: routine を
runで即実行(cron を待たずにテストできる) - Telegram で bot に1通送る → 数秒で返信が返れば導通完了(egress・即応・パス解決がすべて OK)
- 返らない場合は claude.ai の実行履歴で停止した Step を確認(下記トラブルシューティング)
時計はコードに持たせず、cron(起動タイミング)+ session_duration_sec(各回の長さ) で表現します:
| 運用 | cron(UTC) | session_duration_sec |
|---|---|---|
| 24 時間常駐 | 実測上限の間隔で複数回(例 4h ごと = 0 15,19,23,3,7,11 * * * = JST 0/4/8/12/16/20 時) |
実測上限と同程度(例 14400 = 4h) |
| 平日 9–17 時 | 0 0-7 * * 1-5(JST 9–16 時 = UTC 0–7 時) |
3600〜7200 |
cron は UTC。JST から 9 時間引きます(JST 9:00 = UTC 0:00)。1セッションの実行上限はプラットフォーム依存で、Claude Code Routines のコンテナは実測で約 4 時間程度(変動しうる)で終了します。常駐させたい場合は
session_duration_secを実測上限と同程度にし、cron をその間隔で回します——枠が上限より長くても途中で終了し、次の cron が lease / offset の冪等性で継続します(隙間メッセージは Telegram の ~24h 保持で取りこぼしません)。逆に「1日1回 cron + 長大な枠(例86340)」では、上限で切れた後に次の起動まで沈黙するため常駐には不向きです。
| 症状 | 原因 | 対応 |
|---|---|---|
host_not_allowed(Step 3) |
egress 未開通 | network policy に api.telegram.org を追加 |
| exit 2(config invalid) | config.json 欠損 or env 欠損 | show-config で確認 → init-config 再生成、Environment の token/chats を確認 |
| exit 3(auth failed) | bot token 不正 | BotFather で token を確認・再生成 |
| exit 4(lease conflict) | 他セッションが保持中 | 自己治癒の正常動作(重複起動防止)。放置でよい |
| Step 0 でパス解決失敗 | 2リポ配置の不整合 | sources に基本設定リポ+非公開リポの両方があるか、config の private_dir が cwd 親起点か確認 |
| 返信が返らない | egress or 認可 | chat_id が AUTHORIZED_CHATS に入っているか、api.telegram.org egress が通っているか |
| 管理表が毎回空に戻る | registry_sync 無効 or worktree 未 provisioning or git 認証不足 |
config の registry_sync:true / registry_dir(独立 worktree)を確認 → bootstrap の registry worktree provisioned/refreshed ログと固定ブランチへの push 認証(git credential)を確認(DESIGN §3.6) |
registry fetch failed(起動時) |
固定ブランチ未作成 or git 認証不足 | 初回は対象ブランチが空でも継続(前回ローカル状態で起動)。git 認証(PAT 等)が Environment にあるか確認 |
| 管理表は埋まっているのに、秘書が登録済みのタスク・方針を毎回忘れる | 起動時に管理表を並べて list している(肥大した表は出力上限を超え、コンテキストに載らないまま exit 0 する=沈黙失敗) |
起動時オリエンテーションは python scripts/main.py orientation の一撃で行う(bootstrap が ready の直前に案内を出す)。単表 list が 200KB を超えると stderr に警告が出るので、それを合図に orientation / get --key へ切り替える(→ DESIGN §3.12) |
管理表が空=記憶なし稼働(stderr に WARNING: ... EMPTY tables) |
registry_dir が独立 worktree でない(dev ツリー内サブディレクトリ=旧構成) |
registry_dir を独立 worktree 値(ts-registry-wt)にする。bootstrap の registry worktree provisioned/refreshed ログを確認(→ DESIGN §3.6) |
add / import / wal-append が exit 2 で落ちる(stderr に unknown field(s): ... や主題の候補列挙) |
書き込み口の fail-closed——トップレベルの未知キー・語彙外の subject・許可集合外の category を弾いている(v1.9.0 で add / import、v1.11.0 で wal-append も同じ関門へ) |
stderr が原因(キー名・候補)を出すので、それを見てレコードを直してから再実行する。typo キーを黙って捨てないための仕様で、read 経路(list / get / orientation)は従来どおり読める。wal-append はログを書く前に止まるので、弾かれた intent は残らない(→ DESIGN §3.7/§3.8/§3.12) |
起動のたびに stderr へ wal redo: dead <表> key=<key>: <理由> が出る |
v1.11.0 の redo 検証で落ちた intent が dead に隔離されている=「登録すると約束したのに反映できていない」やり残しの記録(期限で消えない) |
理由を見て二つの出口のどちらかを取る——①正しい payload で同じ key を add し直す(次回 redo の settle が done 化=自己治癒)/②履行しないと決めたなら wal-drop --kind <表> --key <key> で畳む。放置すると毎起動出続ける(→ DESIGN §3.7) |
- 仕様 SSoT: SKILL.md
- 起動手順: ROUTINE_PROMPT.md
- 構造地図: STRUCTURE.md
- セキュリティ正典: SECURITY.md
- ローカル動作確認: README.md