Sign inSign up

superbizon007/schedule-agent

By superbizon007

Updated 5 months ago

A long-running A2A agent that fires other agents on a schedule.

Image
Machine learning & AI
0

506

superbizon007/schedule-agent repository overview

Schedule Agent

A long-running A2A agent that fires other agents on a schedule. Supports two trigger types:

  • Cron — standard 5-field cron expressions with timezone support
  • Sensor — polls any A2A agent on a configurable interval; fires when it returns {"triggered": true}

Accepts schedule management commands as either natural language (parsed by an LLM) or structured JSON. Persists all schedules and run history in SQLite.

How it works

  1. Register agents — tell the schedule agent about available A2A agents (name, URL, API key).
  2. Create schedules — describe what to run and when, in plain English or JSON.
  3. Scheduler loop — a background async loop ticks every 10 seconds, checks all enabled schedules, and dispatches to the target agent via A2A message/stream when a trigger fires.
  4. Run history — every dispatch result (status, duration, error) is recorded in the database.
Register:  "register the terminal agent at https://terminal:443/"
           → stored in agents table

Create:    "Run the ETH price report every weekday at 9am New York time"
           → LLM parses → cron "0 9 * * 1-5" tz "America/New_York"
           → stored in schedules table

Loop tick (every 10s):
    cron:   now >= next_run_at  → dispatch to target agent
    sensor: poll_interval elapsed → call sensor agent
                                 → if {"triggered": true} → dispatch

Project structure

app/
  models/schedule.py       Data models: ScheduleEntry, Trigger, AgentRegistration, ParsedScheduleRequest
  store/
    orm.py                 SQLAlchemy ORM (ScheduleRow, RunHistoryRow, AgentRow)
    base.py                Abstract ScheduleStore interface
    sqlite.py              SQLiteScheduleStore (aiosqlite)
  scheduler/
    loop.py                SchedulerLoop — async background tick
    dispatcher.py          SSE streaming dispatch to target A2A agent
    sensor.py              query_sensor() — poll sensor agent, parse result
  llm/
    parser.py              parse_schedule_request() — NL → ParsedScheduleRequest via LLM
  server/
    config.py              Settings (pydantic-settings)
    a2a.py                 ScheduleAgentExecutor — JSON + NL command routing
    main.py                FastAPI app with lifespan (store, LLM client, scheduler loop)
    __main__.py            Entry: python3 -m app.server

Configuration

All settings are read from environment variables (or a .env file).

VariableDefaultDescription
API_KEY``Bearer token for A2A endpoint auth (empty = no auth)
PORT8081HTTPS listen port
DB_URLsqlite+aiosqlite:///./schedule.dbSQLite database path
TICK_INTERVAL10Scheduler loop interval in seconds
LLM_URLhttps://api.openai.com/v1LLM base URL for NL parsing
LLM_API_KEY``LLM API key
LLM_MODELgpt-4oModel name for NL parsing
LLM_TIMEOUT30LLM call timeout in seconds

Running

Docker
docker build -t schedule-agent \
  --build-context root=../.. \
  -f Dockerfile ../..

docker run -d \
  -p 8081:8081 \
  -e LLM_API_KEY=sk-... \
  -e API_KEY=mysecret \
  -v schedule-data:/app \
  schedule-agent
Local
pip install -e .
LLM_API_KEY=sk-... python3 -m app.server

A2A interface

The schedule agent exposes a standard A2A endpoint at https://<host>:8081/.

Input can be natural language (any plain text) or a JSON command object.

Natural language examples
Register the terminal agent at https://terminal-agent:443/ with api key secret123

Run the ETH price report every weekday at 9am New York time using the terminal agent

Watch ETH price every 2 minutes using terminal agent, fire a buy order when below $2000

Show my schedules

Disable the ETH price report

Run the price report right now

Delete schedule sched-abc123

When a required field cannot be determined, the agent replies with a clarification question instead of failing.

JSON command reference

All JSON commands have a "command" key. Useful for programmatic / orchestrator use.

Agent registry
{"command": "register_agent", "name": "terminal", "url": "https://terminal-agent:443/", "api_key": "secret", "description": "runs shell commands on Linux"}
{"command": "unregister_agent", "name": "terminal"}
{"command": "list_agents"}
Create a cron schedule
{
  "command": "create",
  "name": "Daily ETH report",
  "trigger": {
    "type": "cron",
    "cron": {"expression": "0 9 * * 1-5", "timezone": "America/New_York"}
  },
  "target": {
    "url": "https://terminal-agent:443/",
    "api_key": "secret",
    "task": "Fetch ETH price from CoinGecko and write a report to /workspace/report.md",
    "timeout": 300
  }
}
Create a sensor schedule
{
  "command": "create",
  "name": "Buy ETH on dip",
  "trigger": {
    "type": "sensor",
    "sensor": {
      "agent_url": "https://terminal-agent:443/",
      "agent_api_key": "secret",
      "task": "Check ETH price via CoinGecko. Return JSON: {\"triggered\": true, \"value\": <price>} if price < 2000, else {\"triggered\": false}",
      "poll_interval": 120
    }
  },
  "target": {
    "url": "https://terminal-agent:443/",
    "api_key": "secret",
    "task": "Place a market buy order for 0.1 ETH",
    "timeout": 60
  }
}
Other commands
{"command": "list"}
{"command": "get", "id": "sched-abc123"}
{"command": "update", "id": "sched-abc123", "name": "New name"}
{"command": "enable",  "id": "sched-abc123"}
{"command": "disable", "id": "sched-abc123"}
{"command": "delete",  "id": "sched-abc123"}
{"command": "run_now", "id": "sched-abc123"}
{"command": "list_history", "id": "sched-abc123", "limit": 20}

Sensor protocol

Any A2A agent can act as a sensor. It receives the configured task text and must return a JSON artifact:

{"triggered": true, "value": 1850.5}

or

{"triggered": false}

The value field is optional and is stored in the run history for reference.

Cron expression reference

ExpressionMeaning
0 9 * * 1-5Every weekday at 09:00
0 */6 * * *Every 6 hours
30 8 * * 1Every Monday at 08:30
0 0 1 * *First day of every month at midnight
* * * * *Every minute (useful for testing)

Timezones use standard IANA names: UTC, America/New_York, Europe/London, Asia/Tokyo, etc.

MCP tools

The agent image exposes an MCP (Model Context Protocol) server on the same port as A2A at /mcp. Any MCP client — Claude Desktop, Cursor, Windsurf, ChatGPT Connectors, OpenAI Agents SDK — can list and invoke these tools using the pod's API_KEY as Bearer.

In production, Core proxies https://schedule-agent.agents.forfetch.ai/mcp → the worker pod's /mcp.

Tool (skill_id)Description
scheduleSchedule tasks using cron expressions or sensor triggers

Input schemas are authored in apps/agents_mcp/app/seed.py. Skills without an explicit schema advertise a single {task: str} freeform parameter.

Tag summary

Content type

Image

Digest

sha256:fb141a510

Size

89.6 MB

Last updated

5 months ago

docker pull superbizon007/schedule-agent