How to Self-Host OpenDuet: Install CopilotKit's Proactive AI Agent and Run Its Morning Brief
Introduction
Most AI assistants sit quietly until you type something. OpenDuet is built for the opposite pattern: it starts your day with a short brief, sorts mail and calendar into what needs you and what can wait, and keeps working on a computer of its own while you step away, returning only when a decision is needed. This tutorial installs it on your own machine, first with the built-in fake Google account so no real mail is involved, then with real Gmail and Google Calendar.
Quick answer
Clone CopilotKit/OpenDuet, install with Bun, link a free CopilotKit Intelligence project, start it with scripts/start.sh, and open localhost:3010 to run the morning brief with approvals on.
Evidence
OpenDuet is very new, and the numbers say so plainly. The repository was created on October 21, 2026, and its GitHub page showed 1,365 stars, 166 forks, and 73 commits as of October 29, 2026, just eight days later. That is fast attention for a project whose own badge reads “early development,” so read the star count as curiosity and early adoption, not proof of maturity. The code is MIT licensed, which matters because the whole point of the project is that you can copy and adapt it.
The project’s own framing states it plainly. The OpenDuet repository says: “OpenDuet does not wait to be asked. It starts your day with a short brief, keeps working on a computer of its own while you step away, and comes back only when something needs you.” It adds the safety rule shaping the whole design: “Before it sends, pays, signs, or deletes anything, it shows you exactly what it is about to do and waits for your answer.” That pair is the product: proactivity on one side, an approval gate on the other.
The architecture backs the claim up in a specific way. OpenDuet runs on OpenBot, CopilotKit’s open-source, self-hosted agent platform, and the OpenBot page describes the foundation it inherits: the server, the app, each agent’s computer, the approval boundary, and the audit trail. OpenDuet adds the morning brief, Tasks, Make, and its own Bots and skills on top, all in one folder, openbot/examples/openduet, so you can customize it there while OpenBot fixes still arrive underneath.
One more honest limit belongs here, not in troubleshooting. The README states that no hosted or deploy guide for OpenDuet has been published yet, and neither has an OpenDuet image, so this Quick start is the supported way to run it today. The Docker and Helm guides in the OpenBot docs deploy plain OpenBot, not OpenDuet.
Prerequisites
- A machine with Docker running, for agent container computers and Postgres.
- Bun 1.3 or newer, plus Node for
npx, which runs the CopilotKit CLI. - A model key. The default OpenDuet Bot runs OpenAI’s
gpt-5.6-terra, set inopenbot/examples/openduet/model.yaml, so an OpenAI key is the default path. Anthropic is supported as an alternative, covered in step 4. - A free CopilotKit Intelligence project. Intelligence is required: it keeps threads and memory, and the server will not start without its key. The free Developer plan is enough.
- A Google account only for the final step. The fake Google trial in step 5 needs none.
Step-by-step guide
Step 1: Clone the repository and install dependencies
Run every command in this section from the repository root. Start with the clone, then copy the example environment file and install:
git clone https://github.com/CopilotKit/OpenDuet.git
cd OpenDuet
cp .env.example .env
bun install
The .env file holds your keys and addresses: do not commit it or paste it into a chat log or issue report. If something already uses Postgres port 5432, set POSTGRES_PORT in .env to a free port and change the port in DATABASE_URL to match, before you start anything.
Step 2: Sign in and pick a CopilotKit Intelligence project
Sign in with the CopilotKit CLI, pick a project, and run the learning setup script:
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
bun openbot/scripts/setup-learning.ts
Project selection writes the key to .env as CPK_INTELLIGENCE_API_KEY. The server reads INTELLIGENCE_API_KEY instead, so the last command finishes the job: it ensures the project has an openbot Learning container, creating one if needed, then copies the key over and sets CPK_INTELLIGENCE_LEARNING_CONTAINER_ID=openbot. If .env already has INTELLIGENCE_API_KEY, the script keeps it and only checks the container. Run it from the repository root, not from openbot/, since it reads .env and .copilotkit/ from its working directory.
Step 3: Start OpenDuet and open it
With Intelligence linked, start everything with the provided script:
bash scripts/start.sh
Then open http://localhost:3010. The script starts Postgres and each Bot’s computer in Docker, applies migrations, and starts the API server, routine worker, and app, checking each answers before printing next steps. To stop later, run bash scripts/stop.sh, which stops the app, worker, API server, and Docker services, and removes this install’s Bot computers. The database, each Bot’s files, and its browser profile are Docker volumes, so they survive restarts. Add --keep-computers to leave Bot computers running.
On first run, OpenDuet speaks first: it greets you, and with Gmail and Calendar not yet connected, it says what it can do now and shows the card to connect them. Onboarding ends on a setup checklist marking each dependency, Intelligence, the model key, Google, Gmail and Calendar, and notifications, as Ready, Not checked, or Needs setup, with how to fix it. Reopen it any time under Settings → Setup.
Step 4: Set the model key
Put your model key in .env before you start, or restart after adding it, since the API reads .env only when it starts. For the default OpenAI model, that is:
OPENAI_API_KEY=your-key-here
To use another OpenAI model, change default_model in openbot/examples/openduet/model.yaml, or in your copy of that folder (see step 7). Note that BOT_MODEL alone does not change an OpenAI model: it applies only when OPENAI_BASE_URL is also set to an OpenAI-compatible endpoint. For Anthropic, set BOT_PROVIDER=anthropic and ANTHROPIC_API_KEY=your-key-here; the model is BOT_MODEL if set, else claude-sonnet-4-5. After changing model settings, check Settings → Setup, which says whether the key works. You can turn off CopilotKit’s usage telemetry, sent tagged OpenDuet, with COPILOTKIT_TELEMETRY_DISABLED=true or DO_NOT_TRACK=1.
Step 5: Try it with the fake Google account first
This step makes OpenDuet safe to learn on: you can exercise the morning brief, triage, and approvals without granting access to real mail. Start the fake Google server, which serves an invented inbox and calendar:
bun openbot/scripts/fake-google/server.ts --port 4900
Then, in .env, set OPENDUET_FAKE_GOOGLE_URL=http://127.0.0.1:4900, restart with bash scripts/stop.sh and bash scripts/start.sh, and open /admin/plugins/google-workspace. Turn on Enable for this deployment, open OAuth client and paste any client ID and secret, since the fake accepts anything, then press Refresh tools. Grant the connector’s tools to the OpenDuet Bot at /admin/plugins/google-workspace/bots/openduet, then open /connections/google-workspace and press Connect. The fake consents at once, as maya@marlowceramics.com. Confirm what OpenDuet sent with curl http://127.0.0.1:4900/__fake/sent.
With the fake account connected, open Chat and find the morning brief already there: what needs you and why, what can wait, today’s calendar, and anything it could not check, posted once a day however many tabs or devices you open. On a row that needs you, press Start to hand that email to OpenDuet, and watch the approval flow: a changing action pauses with Refuse, Allow once, or Always allow, and a message to another person always asks once, showing who it goes to and what it says.
Step 6: Connect real Gmail and Google Calendar
Gmail and Calendar need a Google OAuth client, which an administrator registers once, after which each person connects their own account under Connections. With the default .env you are the administrator, and Settings → Setup shows which steps are still open and links to each page. The Google Workspace plugin guide covers the Google Cloud steps: the two APIs to enable, the consent screen, and the OAuth client.
One setting trips people up: connecting needs OPENBOT_PUBLIC_URL, the address Google sends people back to. .env.example sets it to http://localhost:3001, so change it if you move SERVER_PORT, and use the public address once deployed. To switch from fake to real Google, remove OPENDUET_FAKE_GOOGLE_URL, restart, and connect again, because the stored sign-in belongs to the fake. After connecting, OpenDuet reads mail and today’s calendar, and sends a reply only after you answer.
Once real mail is flowing, use the Tasks tab as your working surface: what needs you, what OpenDuet suggests from background research, and what it is working on, moving from Working to Ready for review or Needs input, and to Resolved when you check one off. A failed run says why, with Try again where a retry can help.
Step 7: Make it your own, and add a routine
OpenDuet is meant to be copied. Everything that makes it OpenDuet lives in openbot/examples/openduet: brand.yaml for the name, agents.yaml for Bots and instructions, channels.yaml for conversations, model.yaml for provider and model, and skills.yaml for / instructions. Copy the folder, change it, and point TENANT_PACKAGE_DIR in .env at your copy, relative to openbot/server. OpenBot’s code underneath stays in openbot/, so its fixes can still be brought in.
Two features are worth trying once the basics work. First, ask OpenDuet to do something on a schedule: routines run as you, and you will find them in /routines. Second, choose what it must ask you about first in /settings/approvals, so the boundary matches your tolerance before you hand it a task touching other people. For research, the Bot ships a public-web skill: an administrator enables a connector and grants its search and fetch tools, then /research-public-web can compare sources and make a brief with source links. Other connected apps are governed MCP connectors, including Google Drive and Notion, granted to an agent before use.
For comparison, the tstack tutorial shows a skills bundle inside Claude Code and Codex, the ub-mode tutorial shows a single skill enforcing code quality gates, and the complete n8n guide covers workflow automation.
Troubleshooting
The server will not start, and the error mentions Intelligence
Intelligence is required, and the server will not start without its key. Check that .env contains INTELLIGENCE_API_KEY, not only CPK_INTELLIGENCE_API_KEY, and re-run bun openbot/scripts/setup-learning.ts from the repository root to copy the key and verify the Learning container. Then check Settings → Setup, which reports the real answer from Intelligence.
Port 5432 is already taken
If Postgres cannot bind, set POSTGRES_PORT in .env to a free port and change the port in DATABASE_URL to match, then restart with bash scripts/stop.sh and bash scripts/start.sh. Do not just change one of the two, or the app will talk to a port nothing is listening on.
Gmail connects, but the morning brief shows nothing it could not check
First confirm the connector’s tools were granted to the OpenDuet Bot at /admin/plugins/google-workspace/bots/openduet, not only enabled for the deployment. If you previously used the fake Google, remember the stored sign-in belongs to the fake: remove OPENDUET_FAKE_GOOGLE_URL, restart, and connect again. Also confirm OPENBOT_PUBLIC_URL matches the API’s port, since Google sends people back through it.
An action is stuck waiting, or a login wall appears
A stuck action is usually the approval boundary working as designed: open the task for a pending Allow once, Always allow, or Refuse decision, and check Tasks for a Needs input state. For a login wall or two-factor prompt on the agent’s computer, it asks for help and you can take the wheel, and a site password goes into a masked box, reaching the site without entering the agent’s conversation.
The setup checklist says Not checked for something you configured
A sleeping Bot computer reads Not checked until it is running and Check again succeeds, so wait for the start script’s health checks and press Check again rather than re-entering values. A configured URL alone no longer means Ready: the checklist authenticates against the provider, so a wrong key or blocked network path still shows as not ready.
FAQ
What is OpenDuet, exactly?
OpenDuet is an open-source proactive AI agent template, built by CopilotKit on OpenBot. It triages mail and calendar, posts a morning brief, works on its own computer while you are away, and asks approval before sending, paying, signing, or deleting.
Do I need a Google account to try OpenDuet?
No. The repository ships a fake Google server with an invented inbox and calendar, so you can run the morning brief and approval flow before touching real mail. Remove the fake setting, restart, and connect again to switch to real Google.
Is OpenDuet the same as OpenBot?
No. OpenBot is the platform underneath: server, app, agent computers, approval gateway, audit trail, sign-in, and Slack and Teams channels. OpenDuet is one assistant built on it, adding the morning brief, Tasks, Make, and its Bots and skills in openbot/examples/openduet.
What does OpenDuet cost to run?
The code is MIT licensed, and the README says the free CopilotKit Intelligence Developer plan is enough. You still pay for your chosen model, for example the default OpenAI model, plus the machine running Docker and Postgres.
Can OpenDuet send email or pay for things without asking?
By design, no. Defaults ask before sending, paying, signing, or deleting, and every action passes a gateway that checks policy and writes an audit record first. A message to another person always asks once, showing recipient and text.
Is OpenDuet production ready?
Not yet, by its own label: the badge says early development, and the README says to expect things to move. Treat it as a local preview, not a finished product for a whole team, with no hosted or deploy guide published yet.
Conclusion
OpenDuet is a small, honest preview of a bigger idea: an agent that reaches out first, with a morning brief and a triage queue, while an approval gateway and audit trail stand between it and anything it cannot undo. Install it locally, learn it on the fake Google account, connect real Gmail and Calendar only when the approval flow feels right, then make it your own by copying openbot/examples/openduet. Next, try a routine in /routines, or compare it with the tstack skills tutorial.
Frequently asked questions
What is OpenDuet, exactly?
OpenDuet is an open-source template for a proactive AI agent, built by CopilotKit on top of its self-hosted OpenBot platform. It does not wait for a prompt: it triages your mail and calendar, posts a morning brief, keeps working on its own computer while you are away, and asks for approval before any action that sends, pays, signs, or deletes.
Do I need a Google account to try OpenDuet?
No. The repository ships a fake Google server for tests and demos, with an invented inbox and calendar, so you can run the morning brief and approval flow before touching real mail. Switch to real Google later by removing the fake Google setting, restarting, and connecting again.
Is OpenDuet the same as OpenBot?
No. OpenBot is the platform underneath: the server, the app, each agent's computer, the approval gateway, the audit trail, sign-in, and the Slack and Teams channels. OpenDuet is one assistant built on that platform, adding the morning brief, Tasks, Make, and its own Bots and skills, all in the openbot/examples/openduet folder.
What does OpenDuet cost to run?
The code is MIT licensed, and the README says the free CopilotKit Intelligence Developer plan is enough, since Intelligence is required for threads and memory. You still pay for whatever model you choose, for example the default OpenAI model, plus the machine that runs Docker and Postgres.
Can OpenDuet send email or pay for things without asking?
By design, no. Defaults ask before sending, paying, signing, or deleting, and every action passes a gateway that checks policy and writes an audit record first. A message to another person always asks once, showing recipient and text.
Is OpenDuet production ready?
Not yet, by the project's own label: the repository badge says early development, and the README says to expect things to move. Treat it as a working preview to run locally and learn from, not as a finished product to roll out to a whole team, and note that no hosted or deploy guide has been published yet.