2. An Agent That Works Every Morning
We will build an agent that researches generative AI news at 8 a.m. every morning and automatically updates a GitHub Pages site. The uv and authentication setup is the same as in 3. Create an Agent with the SDK; we will create a new project for this page. All GitHub operations are done with gh (the GitHub CLI), except for issuing the token (done in the web UI).
On this page, we will use the following Managed Agents features for the first time.
| Feature | Role |
|---|---|
| Scheduled deployments | A mechanism that automatically creates sessions on a cron schedule |
| GitHub repository resources | A mechanism that mounts a repository into the sandbox and pushes safely through a proxy |
1. Create the project
Section titled “1. Create the project”Create a project, move into its folder, and install the Claude SDK.
uv init ai-news-agentcd ai-news-agentuv add anthropic2. Set up the GitHub CLI
Section titled “2. Set up the GitHub CLI”-
Install the GitHub CLI.
Terminal window winget install --id GitHub.cliTerminal window brew install ghAfter installing, reopen your terminal (or PowerShell).
-
Log in to GitHub. When prompted, choose “GitHub.com”, “HTTPS”, and “Login with a web browser”, then follow the browser instructions to authenticate.
Terminal window gh auth login
3. Create the public repository
Section titled “3. Create the public repository”-
Create a public repository for the site (on the free plan, GitHub Pages only works with public repositories).
Terminal window gh repo create ai-news-site --public --add-readme --description "AI news auto-updated by Claude Managed Agents" -
Enable GitHub Pages (this configuration publishes the root of the main branch).
Terminal window gh api "repos/$(gh api user -q .login)/ai-news-site/pages" -X POST -f "source[branch]=main" -f "source[path]=/" -
Check the public URL and note it down.
Terminal window gh api "repos/$(gh api user -q .login)/ai-news-site/pages" -q .html_urlA URL like
https://your-username.github.io/ai-news-site/will be displayed.
4. Create the agent and deployment
Section titled “4. Create the agent and deployment”-
Issue a token that lets the agent push to the repository. Open the Fine-grained personal access token creation page and click “Generate token” with the following settings.
Field Setting Token name ai-news-site-agentExpiration 7 days (a short expiration is recommended) Repository access ”Only select repositories” → select ai-news-sitePermissions From Add permissions, addContentsand set its access toRead and write.Note down the token that starts with
github_pat_. -
Set the token you issued as an environment variable.
Terminal window $env:GITHUB_TOKEN = "your github_pat_ token here"Terminal window export GITHUB_TOKEN="your github_pat_ token here" -
Create
setup_news.pyin the project folder and save the following content. ReplaceGITHUB_REPO_URLwith your own repository URL.setup_news.py import jsonimport osfrom anthropic import Anthropicclient = Anthropic()GITHUB_REPO_URL = "https://github.com/your-username/ai-news-site"GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]################################ 1. Create the environment###############################environment = client.beta.environments.create(name="News-environment-adv",config={"type": "cloud","networking": {"type": "unrestricted"},},)print(f"environment: {environment.id}")################################ 2. Create the agent###############################agent = client.beta.agents.create(name="News Site Agent ADV",model="claude-sonnet-5",description="An agent that researches generative AI news and updates a GitHub Pages site.",system=("You are the update agent for an AI news site. ""Use web search to research today's generative AI news, and update index.html ""in the repository mounted at /workspace/site. Write the site in English, as ""simple, easy-to-read HTML (with inline CSS). If there is existing content, add ""the new articles at the top under a dated heading and keep the past entries. ""When you are done, use git config to set user.name to 'AI News Bot' and ""user.email to 'ai-news-bot@example.com', then commit the changes and push ""to main on origin."),tools=[{"type": "agent_toolset_20260401", "default_config": {"enabled": True}}],)print(f"agent: {agent.id}")################################ 3. Create the scheduled deployment (runs at 8 a.m. every morning)###############################deployment = client.beta.deployments.create(name="Daily AI news update",agent=agent.id,environment_id=environment.id,initial_events=[{"type": "user.message","content": [{"type": "text","text": "Research 3 major generative AI news stories from today, then update the site and push.",}],}],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"Upcoming runs: {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("Saved IDs to ids_news.json")A deployment is a “session blueprint plus a schedule”.
initial_eventsis the instruction sent at every launch,scheduleis the cron expression and timezone, andresourcesis the repository (and its push token) mounted on every run. -
Run the script.
Terminal window uv run setup_news.pyenvironment: env_0183BKdCPtvzBtf8SAFJG2rBagent: agent_01JLqsExMaqmJKFwVqqHAZ49deployment: depl_017BiAPxX6gBDqH9vgroemxpUpcoming runs: [datetime.datetime(2026, 7, 5, 23, 0, ...), datetime.datetime(2026, 7, 6, 23, 0, ...)]Saved IDs to ids_news.jsonThe upcoming runs are displayed in UTC (23:00 UTC = 8 a.m. Japan time).
5. Test with a manual run
Section titled “5. Test with a manual run”There is no need to wait until 8 a.m. Deployments can also be run manually.
-
Create
run_news_once.pyin the project folder and save the following content.run_news_once.py import jsonimport timefrom anthropic import Anthropicclient = Anthropic()with open("ids_news.json") as f:ids = json.load(f)# Run manually without waiting for the scheduleclient.beta.deployments.run(ids["deployment_id"])print("Triggered a manual run")# Get the session ID from the run recordssession_id = Nonefor _ 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_idbreakif run.error:print(f"Run error: {run.error.type}: {run.error.message}")raise SystemExit(1)if session_id:breakprint(f"session: {session_id}")# Wait for completion while printing the session eventsstream = client.beta.sessions.events.stream(session_id=session_id)for event in stream:if event.type == "agent.tool_use":print(f"[tool: {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":breakelif event.type == "session.status_terminated":breakstream.close()print("\nDone") -
Run the script. It takes a few minutes from researching the news to pushing.
Terminal window uv run run_news_once.pyTriggered a manual runsession: sesn_013PNcoKdf8j9PK4PmorFb9e[tool: web_search][tool: web_fetch]...index.html does not exist yet, so I will create it.[tool: write]I verified how it renders in a browser; now configuring git, committing, and pushing.[tool: bash]The push is complete. I updated the site with the following content....Done -
Open the public URL you noted in step 2 in your browser, and you will see the news page the agent created (it can take 1-2 minutes after the push for changes to appear). Take a look at the repository’s commit history as well.
Terminal window gh repo view ai-news-site --web
6. Stop the schedule
Section titled “6. Stop the schedule”-
Create
pause_news.pyin the project folder and run it.pause_news.py import jsonfrom anthropic import Anthropicclient = Anthropic()with open("ids_news.json") as f:ids = json.load(f)deployment = client.beta.deployments.pause(ids["deployment_id"])print(f"Paused deployment {deployment.id} (status: {deployment.status})")Terminal window uv run pause_news.pyManual runs (
run_news_once.py) are still possible while paused. To resume the schedule, useclient.beta.deployments.unpause(...).
Summary
Section titled “Summary”- A scheduled deployment is a “session blueprint plus a cron schedule”. A new session is created automatically every time the schedule fires.
- When you mount a repository with the
github_repositoryresource, the token is injected by the git proxy, so you can push without placing any secrets inside the sandbox. - For the token you hand over, use a fine-grained PAT scoped down to the minimum target repository, permissions, and expiration.
- Test with a manual run via
deployments.run(), and stop the schedule withpause(orarchive) when you are done.
Great work! Please share your thoughts so far in a post on X.
Share your thoughts on X