コンテンツにスキップ

2. 毎朝働くエージェント

毎朝8時に生成AIのニュースを調査して、GitHub Pagesのサイトを自動更新するエージェントを作ります。uvと認証のセットアップは3. SDKでエージェントを作成と同じ前提で、このページ用に新しいプロジェクトを作って進めます。GitHub側の操作は、トークンの発行(Web画面)を除いてgh(GitHub CLI)で行います。

このページでは、Managed Agentsの次の要素を新しく使います。

要素役割
スケジュールデプロイメントcronスケジュールでセッションを自動作成する仕組み
GitHubリポジトリリソースサンドボックスにリポジトリをマウントし、プロキシ経由で安全にpushする仕組み

プロジェクトを作成し、そのフォルダーに移動して、Claude SDKをインストールします。

Terminal window
uv init ai-news-agent
cd ai-news-agent
uv add anthropic
  1. GitHub CLIをインストールします。

    Terminal window
    winget install --id GitHub.cli

    インストール後、ターミナル(またはPowerShell)を開き直してください。

  2. GitHubにログインします。聞かれたら「GitHub.com」「HTTPS」「Login with a web browser」を選び、ブラウザの案内に沿って認証します。

    Terminal window
    gh auth login
  1. サイト用の公開リポジトリを作成します(GitHub Pagesは無料プランでは公開リポジトリのみ使えます)。

    Terminal window
    gh repo create ai-news-site --public --add-readme --description "AI news auto-updated by Claude Managed Agents"
  2. GitHub Pagesを有効化します(mainブランチ直下を公開する設定です)。

    Terminal window
    gh api "repos/$(gh api user -q .login)/ai-news-site/pages" -X POST -f "source[branch]=main" -f "source[path]=/"
  3. 公開URLを確認して控えておきます。

    Terminal window
    gh api "repos/$(gh api user -q .login)/ai-news-site/pages" -q .html_url

    https://ユーザー名.github.io/ai-news-site/のようなURLが表示されます。

4. エージェントとデプロイメントを作成

Section titled “4. エージェントとデプロイメントを作成”
  1. エージェントがリポジトリにpushするためのトークンを発行します。Fine-grained personal access tokenの発行画面を開き、次の内容で「Generate token」します。

    項目設定
    Token nameai-news-site-agent
    Expiration7 days(短めを推奨)
    Repository access「Only select repositories」→ ai-news-siteを選択
    PermissionsAdd permissionsからContentsを追加。AccessをRead and writeに。

    表示されたgithub_pat_で始まるトークンを控えます。

  2. 発行したトークンを環境変数に設定します。

    Terminal window
    $env:GITHUB_TOKEN = "ここにgithub_pat_のトークン"
  3. プロジェクトのフォルダーにsetup_news.pyを作成し、以下の内容を保存します。GITHUB_REPO_URLは自分のリポジトリのURLに置き換えてください。

    setup_news.py
    import json
    import os
    from anthropic import Anthropic
    client = Anthropic()
    GITHUB_REPO_URL = "https://github.com/あなたのユーザー名/ai-news-site"
    GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]
    ###############################
    # 1. 環境を作成
    ###############################
    environment = client.beta.environments.create(
    name="News-environment-adv",
    config={
    "type": "cloud",
    "networking": {"type": "unrestricted"},
    },
    )
    print(f"environment: {environment.id}")
    ###############################
    # 2. エージェントを作成
    ###############################
    agent = client.beta.agents.create(
    name="News Site Agent ADV",
    model="claude-sonnet-5",
    description="生成AIニュースを調査してGitHub Pagesのサイトを更新するエージェント。",
    system=(
    "あなたはAIニュースサイトの更新エージェントです。"
    "Web検索で当日の生成AI関連ニュースを調査し、/workspace/site にマウントされた"
    "リポジトリの index.html を更新してください。サイトは日本語で、シンプルで読みやすい"
    "HTML(CSSはインライン)にしてください。既存の内容がある場合は、日付の見出しを付けて"
    "新しい記事を上に追記し、過去分は残してください。"
    "作業が終わったら、git config で user.name を 'AI News Bot'、user.email を "
    "'ai-news-bot@example.com' に設定したうえで、変更をコミットして origin の main に"
    "プッシュしてください。"
    ),
    tools=[{"type": "agent_toolset_20260401", "default_config": {"enabled": True}}],
    )
    print(f"agent: {agent.id}")
    ###############################
    # 3. スケジュールデプロイメントを作成(毎朝8時に実行)
    ###############################
    deployment = client.beta.deployments.create(
    name="毎朝のAIニュース更新",
    agent=agent.id,
    environment_id=environment.id,
    initial_events=[
    {
    "type": "user.message",
    "content": [
    {
    "type": "text",
    "text": "今日の生成AI関連の主要ニュースを3件調査し、サイトを更新してプッシュしてください。",
    }
    ],
    }
    ],
    schedule={
    "type": "cron",
    "expression": "0 8 * * *",
    "timezone": "Asia/Tokyo",
    },
    resources=[
    {
    "type": "github_repository",
    "url": GITHUB_REPO_URL,
    "mount_path": "/workspace/site",
    "authorization_token": GITHUB_TOKEN,
    }
    ],
    )
    print(f"deployment: {deployment.id}")
    print(f"次回の実行予定: {deployment.schedule.upcoming_runs_at[:2]}")
    with open("ids_news.json", "w") as f:
    json.dump(
    {
    "environment_id": environment.id,
    "agent_id": agent.id,
    "deployment_id": deployment.id,
    },
    f,
    indent=2,
    )
    print("IDをids_news.jsonに保存しました")

    デプロイメントは「セッションの設計図+スケジュール」です。initial_eventsが毎回の起動時に送られる指示、scheduleがcron式とタイムゾーン、resourcesが毎回マウントされるリポジトリ(とpush用トークン)になります。

  4. スクリプトを実行します。

    Terminal window
    uv run setup_news.py
    environment: env_0183BKdCPtvzBtf8SAFJG2rB
    agent: agent_01JLqsExMaqmJKFwVqqHAZ49
    deployment: depl_017BiAPxX6gBDqH9vgroemxp
    次回の実行予定: [datetime.datetime(2026, 7, 5, 23, 0, ...), datetime.datetime(2026, 7, 6, 23, 0, ...)]
    IDをids_news.jsonに保存しました

    実行予定はUTCで表示されます(23:00 UTC = 日本時間の朝8時)。

朝8時を待つ必要はありません。デプロイメントは手動でも実行できます。

  1. プロジェクトのフォルダーにrun_news_once.pyを作成し、以下の内容を保存します。

    run_news_once.py
    import json
    import time
    from anthropic import Anthropic
    client = Anthropic()
    with open("ids_news.json") as f:
    ids = json.load(f)
    # スケジュールを待たずに手動実行
    client.beta.deployments.run(ids["deployment_id"])
    print("手動実行をトリガーしました")
    # 実行レコードからセッションIDを取得
    session_id = None
    for _ in range(30):
    time.sleep(2)
    runs = client.beta.deployment_runs.list(deployment_id=ids["deployment_id"])
    for run in runs:
    if run.session_id:
    session_id = run.session_id
    break
    if run.error:
    print(f"実行エラー: {run.error.type}: {run.error.message}")
    raise SystemExit(1)
    if session_id:
    break
    print(f"session: {session_id}")
    # セッションのイベントを表示しながら完了を待つ
    stream = client.beta.sessions.events.stream(session_id=session_id)
    for event in stream:
    if event.type == "agent.tool_use":
    print(f"[ツール: {event.name}]")
    elif event.type == "agent.message":
    for block in event.content:
    if block.type == "text":
    print(block.text)
    elif event.type == "session.status_idle":
    if event.stop_reason.type != "requires_action":
    break
    elif event.type == "session.status_terminated":
    break
    stream.close()
    print("\n完了しました")
  2. スクリプトを実行します。ニュースの調査からpushまで数分かかります。

    Terminal window
    uv run run_news_once.py
    手動実行をトリガーしました
    session: sesn_013PNcoKdf8j9PK4PmorFb9e
    [ツール: web_search]
    [ツール: web_fetch]
    ...
    index.htmlがまだ存在しないので、新規作成します。
    [ツール: write]
    ブラウザ表示を確認し、git設定・コミット・プッシュを行います。
    [ツール: bash]
    プッシュが完了しました。以下の内容でサイトを更新しました。
    ...
    完了しました
  3. 手順2で控えた公開URLをブラウザで開くと、エージェントが作ったニュースページが表示されます(pushからの反映に1〜2分かかることがあります)。リポジトリのコミット履歴も見てみましょう。

    Terminal window
    gh repo view ai-news-site --web
  1. プロジェクトのフォルダーにpause_news.pyを作成し、実行します。

    pause_news.py
    import json
    from anthropic import Anthropic
    client = Anthropic()
    with open("ids_news.json") as f:
    ids = json.load(f)
    deployment = client.beta.deployments.pause(ids["deployment_id"])
    print(f"deployment {deployment.id} を一時停止しました (status: {deployment.status})")
    Terminal window
    uv run pause_news.py

    一時停止中も手動実行(run_news_once.py)は可能です。スケジュールを再開したいときはclient.beta.deployments.unpause(...)を使います。

  • スケジュールデプロイメントは「セッションの設計図+cronスケジュール」です。スケジュールが来るたびに新しいセッションが自動作成されます。
  • github_repositoryリソースでリポジトリをマウントすると、トークンはgitプロキシが注入するため、サンドボックス内に秘密情報を置かずにpushできます。
  • 預けるトークンは、対象リポジトリ・権限・有効期限を最小に絞ったfine-grained PATを使います。
  • deployments.run()で手動実行してテストし、使い終わったらpause(またはarchive)でスケジュールを止めます。

おつかれさまでした!ここまでの感想を、ぜひXにポストしてください。

感想をXにポストする