Skip to main content
This is Part 2 of the Upsun Task Containers series. In Part 1 we used a lightweight cron to trigger a task container for a heavy database job. Now we keep the exact same trigger pattern — but the task launches an AI agent instead of a shell command.
In Part 1, the task ran a deterministic command: reindex, import, export. That is the natural first step. But a task container is also the ideal home for something less deterministic and more interesting: a background AI agent that reads your project’s logs, reasons about them, and reports back. In this episode we build a small but real agent. On a schedule, a cron triggers a task container that runs OpenCode over your cron and application logs. The agent summarizes what happened, flags anomalies (slow crons, repeated errors, suspicious patterns), and writes a Markdown report — visible in the task logs and saved to a temporary file. No issues created, no pull requests opened yet: just a clean, automated reading of your logs. That groundwork unlocks the autonomous Auto-RCA agent we build in Part 3.
Task containers are currently in prerelease. To enable them on your project, open this prepopulated support ticket and add your project ID before submitting.

Prerequisites

Before starting, make sure you have:

The architecture

The flow is identical to Part 1 — a cron mints a token and triggers the task — except the task now runs a Node.js entry point that drives OpenCode: The agent stays deliberately simple. It does not need the Upsun API token, GitHub access, or write permissions on your repository — it only reads logs and produces text. We add those capabilities, step by step, in the next episodes.

Step 1 - Define the agent task

The task runs a nodejs image and pulls in the opencode-ai package as a dependency so the opencode binary is available at runtime. The container profile is bumped because LLM agents are memory-hungry.
.upsun/config.yaml
Key points:
  • dependencies.nodejs.opencode-ai installs the OpenCode CLI into the task image at build time, so opencode run works without a separate install step.
  • hooks.build adds the official Upsun OpenCode skills. They are optional for pure log reading, but they make the agent Upsun-aware and set the stage for Part 3.
  • container_profile: "HIGH_MEMORY" gives the agent enough memory to run a model session comfortably.
  • relationships.app lets the agent reach the application over HTTP if you later want it to pull logs from an endpoint instead of the filesystem.
The token-optimization plugins from Part 2 of the OpenCode series work here too. Reading log files is exactly the kind of output-heavy workload that benefits from opencode-snip — well worth wiring in once your agent goes beyond a proof of concept.

Step 2 - Provide the LLM API key

OpenCode needs a provider key to talk to a model. Set it as a sensitive environment-level variable so it is injected into the task container at run time but never committed:
Terminal
Sensitive variables are available to the task exactly as they are to applications — as environment variables — without appearing in your configuration or logs.

Step 3 - Write the agent

The agent is a small Node.js script. It collects the relevant log files, builds a focused prompt, runs OpenCode non-interactively, and writes the resulting report both to the task logs (so it shows up in the activity feed) and to a temporary file.
agent/analyze.js
tmp and instance mounts are reset between runs. The /tmp report exists only while the task runs and is meant for inspection in the same activity. To persist reports across runs, write to a storage mount or push them to a service. Part 3 shows how to push results out of the task entirely (a GitHub pull request).

Step 4 - Trigger the agent from a cron

This is unchanged from Part 1: a tiny cron mints a short-lived token from the container-local broker and POSTs to the task run endpoint. Reuse the same trigger script, pointed at the new task name:
bin/trigger-loganalyzer.sh
And the cron plus the authorization that lets the app trigger the task:
.upsun/config.yaml

Step 5 - Deploy and read the report

Commit and push:
Terminal
Trigger a run manually to test it without waiting for the top of the hour:
Terminal
Then open the activity for the task run and read the streamed report:
Terminal
The agent’s Markdown report appears between the === Log-analysis report === markers, and the path of the saved /tmp copy is printed at the end.

Wrapping up

You now have an AI agent that runs on a schedule, reads your logs, and writes you a health report — all inside an ephemeral task container, with nothing extra running between invocations. The agent stayed read-only and self-contained, which is exactly what you want before handing it more power. In Part 3, we give the agent that power. Instead of reacting on a schedule, it reacts to every 500 error in production: it analyzes the incident with the Upsun MCP server, opens a GitHub issue, and submits a pull request that closes it. That is the full Auto-RCA agent — see you in the next episode.
Last modified on August 31, 2026