# CompanyOS automation runs hourly, on a cron you can set

> Agno's CompanyConfig takes a cron_expr for the Company automation schedule, and AgentOS rewrites an existing schedule to match the next time it starts.

- Published: 2026-10-22
- Author: Yash Pratap Solanky
- Categories: Changelog
- Canonical: https://www.agno.com/blog/companyos-automation-runs-hourly-on-a-cron-you-can-set
- Markdown: https://www.agno.com/blog/companyos-automation-runs-hourly-on-a-cron-you-can-set.md

Agno's `CompanyConfig` now takes a `cron_expr` that controls how often [CompanyOS](https://www.agno.com/blog/introducing-companyos) checks Ready Tasks and authorized Routine proposals. AgentOS writes that value to the runtime-owned `Company automation` schedule at startup, and the default `"0 * * * *"` fires at the top of every hour.

Earlier releases created the schedule with a one-minute cron. On the first start after the upgrade, AgentOS finds the old `* * * * *` row, rewrites its cron and recomputes `next_run_at`. We started AgentOS three times against one SQLite database, once on the previous release and twice on this one:

![Real output from three AgentOS starts on one SQLite database at 21:34 UTC. Before, the Company automation schedule has cron_expr star star star star star and next_run_at 21:35:00 UTC. Now, after a restart on this release, cron_expr is 0 star star star star and next_run_at is 22:00:00 UTC. With CompanyConfig cron_expr set to every five minutes, next_run_at is 21:35:00 UTC.](https://www.agno.com/images/v3-1-9-company-automation-hourly.png)

With the default, a Ready Task or an auto-accepted Routine proposal can wait up to an hour for pickup. A person can still start a Task right away with `POST /company/tasks/{task_id}/runs`. A deployment that wants the old pace sets the cron back:

```python
agent_os = AgentOS(
    db=db,
    company=CompanyConfig(cron_expr="* * * * *"),
    scheduler=True,
)
```

`CompanyConfig` refuses an empty value when you build it. Anything else that is not a cron expression builds fine and is caught at AgentOS startup, by the scheduler's own cron validator, before the poller runs. Both errors below are real output:

```text
# raised by CompanyConfig
CompanyConfig(cron_expr="")
ValueError: cron_expr must be a cron expression

# raised when an AgentOS carrying this config starts up
CompanyConfig(cron_expr="every hour")
ValueError: Invalid cron expression: every hour
```

This release also renames the six Company tools that act on a single Product. Models see the new names, and the earlier names no longer exist, so update any agent or Routine instructions that mention them. The methods on `CompanyTools` change the same way, including the async versions with an `a` prefix such as `aread_product_source`. Company-wide tools and HTTP routes keep their names.

| Earlier name             | New name                 |
| ------------------------ | ------------------------ |
| `list_company_sources`   | `list_product_sources`   |
| `add_company_source`     | `add_product_source`     |
| `read_company_source`    | `read_product_source`    |
| `intake_company_source`  | `intake_product_source`  |
| `create_company_routine` | `create_product_routine` |
| `update_company_status`  | `update_product_status`  |

See the [cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/05_agent_os/30_company/README.md), and learn more about the [AgentOS scheduler](https://docs.agno.com/agent-os/scheduler/overview) in the documentation.
