Quickstart with the demo company

Last updated October 5, 2026

On this page

ok demo creates a small, ready-made software company on your own machine. You can sign in as any of its people, ask its agents for things, watch an agent's action wait for a person, approve it, and read the record of everything that happened. You need no account anywhere and no model key.

By the end of this page you have a working workspace and have followed two approvals from start to finish.

The demo is for development only. Local fakes stand in for every outside system (mail, billing, helpdesk, GitHub, analytics and the rest), so nothing leaves your machine. Its connections may reach any local service over plain http, and every sign-in token is printed in your terminal. Never put the demo on a network you do not control, and never use its state file for real work. For a real company, see Self-hosting, backups and upgrades.

A few terms used on this page:

Term Meaning
Module A packaged part of the company (CRM, Support and so on) that brings its own records, agents, tools and pages. See Modules.
Agent A software worker that plans and acts for a person, inside the limits the company sets. See Agents.
Approval A person's yes or no on one action an agent wants to take. The agent's run waits (it is parked) until someone decides. See Inbox and approvals.
Brain The company's shared records, such as leads and tickets. See Brain.
Stub planner What answers in place of a model when no model key is set. See Without a model key, and with one.

Before you start#

You need the OrchKernel source, Node.js with npm (for the workspace's web pages) and a Rust toolchain. Build once, from the top of the source folder:

sh
(cd ui && npm ci && npm run build)   # builds the workspace's web pages
cargo build --release                # builds the binary, with those pages inside
alias ok=./target/release/orchkernel

The binary is called orchkernel; the alias lets you type ok as this guide does. Build the web pages first: a binary built without them still runs, but the browser shows only "UI not built. Run npm run build in ui/."

Create the demo company#

sh
ok demo

This creates a folder orchkernel-demo in the current folder (use ok demo --dir <path> to put it elsewhere) and prints what it made:

text
Created the demo company in orchkernel-demo (development only).

  people     ada (admin) and fiona, sam, alice, maya, tom, pat, erin, eli
  teams      Sales, Support, Product, Engineering, Founder's office
  modules    crm, sales, marketing, support, support-ops, product, product-ops, tech, founder, context
  records    19 sample records: customers, leads at every stage, open tickets,
             and ticket T-1042 asking for a refund of 250.00 (over the 100.00 cap)
  tools      12 connections, each to a local fake; no real account is used

Start it:

  ok demo serve --dir orchkernel-demo

It ends by pointing at docs/demo.md, a file in the source folder. This page covers the same steps.

The folder holds state.db (the whole company) and a plans folder (see For developers).

Running ok demo again in the same place is refused: "Error: orchkernel-demo already holds a demo company; pass --force to start over". ok demo --force throws the old company away and creates a fresh one.

What is in the demo company#

People and teams#

Id Name Role Team Reports to
ada Ada Park Admin none
fiona Fiona Reyes Founder, leads the Founder's office Founder's office
sam Sam Ortiz Sales lead Sales Fiona
alice Alice Chen Sales rep Sales Sam
maya Maya Patel Support lead Support Fiona
tom Tom Becker Support agent Support Maya
pat Pat Kim Product manager, leads Product Product Fiona
erin Erin Walsh Engineering lead Engineering Fiona
eli Eli Novak Engineer Engineering Erin

Ada governs the company: she alone sees People, Modules and Setup in the sidebar, and she approves what the rules send to an admin. She does not read the Sales or Support records herself.

Modules and agents#

Every department module is enabled and healthy: CRM, Sales, Marketing, Support, Support operations, Product, Product operations, Tech, Founder and Context. Each module's team is bound to the company team of the same name; Marketing's agents work in the Sales team. Directory lists 35 agents, all at the Standard trust tier.

Records#

Collection What is there
Leads 7, at every stage. Northwind Traders and Contoso Health are won (the customers). Litware is "contacted" and waiting on a follow up from Alice.
Contacts 2: Rosa Diaz (Northwind) and Dana Brooks (Litware)
Tickets 5, four of them open, including T-1042
Roadmap items 3: Single sign-on (SAML), Faster CSV export, Mobile app
Feature requests 1: SAML single sign-on, 7 votes
Incidents 1: Export workers saturated (sev2, mitigated)

Who reads what follows the modules' rules, so the same question gets a different answer depending on who asks:

Person Leads Contacts Tickets Incidents
sam (sales lead) all 7 2 no no
alice (sales rep) her own 4 2 no no
maya, tom (Support) no no all 5 1
pat (Product) no no all 5 no
erin, eli (Engineering) no no no 1
ada, fiona no no no no

Everyone reads the roadmap items and the feature request.

The refund over the cap#

Ticket T-1042: Northwind was charged twice for September and asks for 250.00 back. The Support operations module lets an agent refund up to 100.00 on its own; anything over that waits for an admin, whatever the agent's trust tier. So an agent's refund on T-1042 always stops for Ada.

Connections and triggers#

A connection is the company's link to one outside tool server. There is one per tool server, named demo ads, demo apollo, demo billing, demo cms, demo ga4, demo github, demo google, demo gsc, demo helpdesk, demo pagerduty, demo sentry and demo stripe. None has a secret. When the demo runs, each points at a local fake that answers like the real system would.

Every trigger (a schedule, a webhook or a change to the data that starts an agent by itself) is Off, so nothing runs until someone asks. You can turn one on later (see Pause and resume a module).

Start the demo#

sh
ok demo serve

If you created the demo elsewhere, add --dir <path>. The server listens on 127.0.0.1:8080; change it with --bind, for example --bind 127.0.0.1:8811. (The OK_BIND setting is not read here.)

The terminal shows demo: 12 local fakes started; 12 connections point at them and OrchKernel serving on http://127.0.0.1:8080, and prints:

text
OrchKernel demo (development only: local fakes stand in for every tool)

  Workspace   http://127.0.0.1:8080
  Model       none configured: a stub planner answers the walkthrough's asks.
              Set ANTHROPIC_API_KEY (or an llm.yaml) and restart for a real model.
  Egress      development mode: connections may reach loopback over plain http,
              so an admin can point one at any local service.

Sign in by pasting a person's token on the sign-in page (valid 7 days;
the next start revokes these and prints new ones):

  ada    admin                                orchk_34ab…
  fiona  founder, leads the Founder's office  orchk_4838…
  sam    sales lead                           orchk_4b0d…
  alice  sales rep                            orchk_a0ef…
  maya   support lead                         orchk_8d1c…
  tom    support agent                        orchk_c3d4…
  pat    product manager, leads Product       orchk_22e3…
  erin   engineering lead                     orchk_cb52…
  eli    engineer                             orchk_495f…

followed by a short list of first things to try and "Stop with Ctrl+C. Your changes stay in the state file." Each token is longer than shown here.

  • Keep this terminal open. Ctrl+C stops the demo. Everything you do is kept in orchkernel-demo/state.db for the next start.
  • Every start issues new tokens and revokes the ones the previous start printed. After a restart, sign in again with the new ones; an old one is refused with "That token wasn't recognised or has expired."
  • If the address is taken, the start fails with "Error: Address already in use (os error 48)" (the number depends on your system), but only after it has printed the banner and the tokens. Those tokens are no use. Start again with another --bind.
  • Model says whether a real model answers. With no key, the stub planner answers the asks on this page.

Sign in#

  1. Open the Workspace address in a browser. You see the OrchKernel sign-in card: "Sign in with the token an admin gave you.", a Token box and Sign in.
  2. Copy maya's token from the terminal, paste it into Token and press Sign in.
  3. You land on Threads. The sidebar shows Inbox, Threads, Work and Curation, the module pages under their sections (for Maya: Context, Engineering, Marketing, Product, Support), and under Company: Brain, Knowledge, Directory, Governance and Events. At the bottom left: Maya Patel, Support lead, and Sign out.
  4. Click Brain, then Tickets: "5 rows you can read · as Maya Patel", with T-1042 at the top and its refund of $250.00.

To become someone else, press Sign out and paste another person's token. On a phone, the sidebar is behind the menu button at the top left and the inbox is the icon at the top right, with the unread count beside it.

Prefer typing a name to pasting tokens? Start with ok demo serve --dev-auth. It prints no tokens; instead it says the server trusts the x-ok-actor header and lists the ids. On the sign-in page open Development mode (server started with --dev-auth), type a person's id (maya) under Actor id and press Continue as actor. Anyone who can reach the server can then act as anyone, so --dev-auth refuses any address but loopback.

Your first 30 minutes#

Follow these in order: later steps use what earlier ones did.

1. Ask an agent (3 minutes)#

As maya:

  1. Click Threads. Under Talk to an agent, Support · your team lists the Support team's agents: Churn-risk watcher, Knowledge-base writer, QA reviewer, Support Agent, Triage.
  2. Click Support Agent. A page "New conversation with Support Agent" opens, with Support Agent already picked.
  3. Type What is open? and press Ask agent (or Ctrl+Enter, ⌘+Enter on a Mac).
  4. The conversation shows your message, then the agent's answer: a table of the four open tickets (T-1042, T-1043, T-1044, T-1045), then Done: What is open?. The right-hand panel lists the participants and the task, marked Done.

The answer table shows each field's stored value, so money is in cents: T-1042's refund_cents reads 25000, which is $250.00.

Clicking an agent you already have a conversation with opens that conversation again instead of a new one.

Now sign out and sign in as alice. Click Sales Assistant, type Show my pipeline and press Ask agent. You get Alice's four leads only (Contoso Health, Tailspin Toys, Litware, Adventure Works). The agent acts for Alice and reads only what she may read; Sam asking the same question sees all seven. The value column is in cents too (Contoso Health's 1800000 is $18,000.00).

More on conversations and threads: Asking an agent and Threads.

2. Watch a governed write wait (5 minutes)#

Still as alice, in the same conversation with the Sales Assistant:

  1. Type Email a follow up to my contacted lead and press Ask agent.
  2. A notice says "Sales Assistant needs your approval: Send email". The conversation shows an approval card, Send email, marked Pending: "Sales Assistant asks to send email.", To dana@litware.example, Subject "Following up on our demo", and the email's text. Under it, the rule that held it: "Agents never send email without the rep approving the draft". Nothing has been sent. In the right-hand panel the task reads Parked and Approvals lists the card as Pending.
  3. Open Why am I asked?. It lists every check the action passed (Alice's delegation, no pause or kill switch, the skill, the budgets) and the one that stopped it: "A CRM rule requires approval: Agents never send email without the rep approving the draft", then "Alice Chen would be asked, and the run would wait until they decide" and "The policy asks the person it acts for."
  4. Click Inbox in the sidebar if you like: the same card sits under Waiting on you. Come back to the conversation with Threads, then Conversation with Sales Assistant under Your threads.
  5. Press Approve on the card.
  6. The card turns Approved ("Approved by Alice Chen"), and the agent carries on: its answer shows Next follow up three days from today, Sent msg-18c2f1a9 (the message id from the mail fake) and To dana@litware.example. The task reads Done.

To see the other outcome, ask the same thing again and press Reject on the new card. A box opens: "Say why, so the agent and the requester know". Type a reason if you like and press Confirm reject. The card turns Rejected ("Rejected by Alice Chen"), the agent answers "Nothing was done." marked Declined, and the task reads Cancelled. No email is sent.

3. Approve the parked refund as Ada (5 minutes)#

Sign out and sign in as maya.

  1. Threads, then Churn-risk watcher under Talk to an agent.
  2. Type Northwind wants a refund for the double charge and press Ask agent.
  3. The watcher works in rounds: it reads ticket T-1042, looks up Northwind's account in the billing fake, then asks to refund 250.00. After a second or two an approval card appears: Issue a refund or credit, Pending, "Churn-risk watcher asks to issue a refund or credit on behalf of Maya Patel.", Amount $250.00, Invoice inv-2026-09-1042, Reason "Double charge on the September invoice (ticket T-1042)", and the rule: "Goodwill credits by agents over the cap of 100.00 in the account currency per call need an admin, whatever the trust tier". Below it: Waiting for an admin (Ada Park). No notice pops up for this one; the card simply appears in the conversation.
  4. Maya has no Approve button. She leads the team the agent works for, but the rule wants an admin. Why does this need approval? shows the same kind of checks as before, ending "A Support operations rule requires approval: ...", "Ada Park would be asked, and the run would wait until they decide" and "The policy asks anyone with the admin role."
  5. Sign out and sign in as ada. The sidebar's Inbox shows a count.
  6. Click Inbox. Under Waiting on you is the same refund card. Press Approve.
  7. Because this moves money, the card asks "Issue a refund or credit of $250.00? It runs as soon as you approve." with Cancel and Approve $250.00. Press Approve $250.00.
  8. A notice says Approved and the card leaves the inbox.
  9. Sign in as maya again and open Conversation with Churn-risk watcher under Your threads. The card reads "Approved by Ada Park", and the watcher's answer follows: "Refunded after an admin approved it.", Amount $250.00, Invoice inv-2026-09-1042, Refund re_3Rk0a1Lq (the billing fake's refund id). The task reads Done.

Had Ada pressed Reject, no refund would be made and the run would end saying so. More in Inbox and approvals.

4. Read the event log and replay the run (5 minutes)#

As ada:

  1. Click Events. This is the append-only log of everything that happened, newest first; nothing in it can be changed. The line above the list reads "Audit chain: N events, not checkpointed yet", where N is a few hundred by now.
  2. In Type, choose Approval requested. Two rows: "Approval asked of Ada Park for tool.call(support-ops.billing.refund)" and "Approval asked of Alice Chen for tool.call(gmail.send)". (If you tried Reject in step 2, there is a third row for Alice.)
  3. Choose Tool called. Three rows: "support-ops.billing.refund called by Churn-risk watcher", "support-ops.billing.account called by Churn-risk watcher" and "gmail.send called by Sales Assistant". Click a row to see its details: the event number, the time, who did it, the raw type (tool_called) and its data.
  4. Click Work. It opens on Open tasks; click the Runs tab ("Runs (4)", more if you asked other things). Every run is listed with its state, agent, task, steps, cost, tokens and start time.
  5. Click the Churn-risk watcher run (task "Northwind wants a refund for the double charge"). A panel opens: "Churn-risk watcher acting for Maya Patel", then the Trace: Used the skill Churn-risk watching, each Planned the next step, Read Tickets: 1 row, Billing account Ok, Asked for approval, Approval Approved, Issue a refund or credit Ok, a Round line after each round, Kept 1 lesson, and the Output.
  6. Open Replay (raw events) at the bottom. This is the run rebuilt from the event log alone: run_started, each policy_evaluated decision (the refund's reads require_approval with the reason rule support-ops-refunds-need-admin: ...), tool_called, approval_requested, run_parked, approval_resolved by ada, run_resumed, the refund's tool_called and run_finished.

With the stub planner, its planning steps still show as model calls: the events name the model mock-default, and the run counts tokens but costs $0.00. More in Events and the audit log.

5. Pause and resume a module (5 minutes)#

As ada:

  1. Click Modules. It opens on the Catalog tab. Click the Installed tab: all ten modules read Enabled and Ok.
  2. Click Support operations. Its page shows the state, health, version, who set it up and what it requires (Support).
  3. Press Pause. A confirmation says "Pause Support operations? Its agents, tools and triggers stop and its pages hide; data and settings stay." Press Pause. The state turns Paused and the button becomes Resume.
  4. Sign in as maya and open Threads. The Churn-risk watcher, Knowledge-base writer and QA reviewer chips read paused and cannot be clicked, and the Support operations page is gone from the sidebar. In her existing conversation with the watcher, the agent picker shows "Churn-risk watcher (paused by an admin)", so Ask agent stays greyed out. The Support Agent and Triage (the Support module) still work.
  5. Back as ada, open Support operations again and press Resume. There is no confirmation; the state returns to Enabled and Maya's chips work again.
  6. On the same module page, open the Automation tab. It lists the module's four triggers, all Off: Kb morning (weekdays at 9:00), Qa morning (weekdays at 8:00), Churn on ticket change (a change to tickets) and Churn sweep (weekdays at 8:30). Change automation opens a list with a checkbox per trigger and Save. With no model the stub planner answers those runs too; with a real model they cost money, which is why the demo starts with them off.

The Catalog tab lists every module the company could enable; in the demo each one already says Enabled. More in Modules.

Without a model key, and with one#

No key: the stub planner#

With no key, a stub planner answers instead of a model. It is not a model: it answers the asks on this page with fixed plans (the open tickets, the pipeline, the follow up email, the refund). Anything else gets a note instead of an answer. For example, Pat asking the Product Agent "What should we build next quarter?" gets "No model is configured, so the demo's stub planner answered. ...", which names the keys to set, and the task still reads Done. The governance is real either way: the policy checks, the approvals, the fakes' calls and the event log are the same as with a model.

Changes to skills and playbooks run evals, which need a model. Without one, an eval the stub cannot answer shows as not run, never failed, and the change waits. See Changing a skill or playbook.

With a key#

  1. Stop the demo (Ctrl+C).
  2. Set a key, for example export ANTHROPIC_API_KEY=... (or OPENAI_API_KEY, GEMINI_API_KEY, OLLAMA_HOST), or put an llm.yaml in the folder you start from.
  3. Run ok demo serve again. The Model line now names the default model and where it came from ("..., configured from ..."). The server also checks each key in the background and prints a warning for one that is refused.
  4. Sign in with the new tokens and ask anything: the agents plan for real.

What changes and what does not:

Stub planner Real model
Which asks work The ones on this page Any
Exact steps and wording Fixed Vary from run to run
Refund over the cap waits for an admin Yes Yes
Agent's email waits for the rep Yes Yes
Cost Nothing ($0.00 on every run) Model tokens, shown per run under Work

The demo's tickets are restricted customer data, and a model only sees data up to the level it is allowed. From the environment, Anthropic's models and Ollama may take restricted data; the built-in OpenAI and Gemini models stop at confidential, so with only one of their keys the Churn-risk watcher's refund ask is refused for lack of an allowed model. In an llm.yaml, give the model max_sensitivity: restricted. See Models.

Starting over and moving on#

You want to Do
Stop Ctrl+C in the terminal running ok demo serve
Carry on later ok demo serve again, and sign in with the new tokens. Your threads, approvals and runs are still there.
Throw everything away Stop, then ok demo --force, then ok demo serve
Try one real system See Connections and integrations. ok demo serve re-points only connections that still point at 127.0.0.1, so one you point at a real system stays as you set it.
Set up a real company Do not start from the demo. Start from a clean state with ok init; see Setting up a company and Self-hosting.

Not possible yet#

  • Running the demo for other people over a network. It is for one person on one machine; --dev-auth refuses any address but loopback.
  • Changing how long the printed tokens last (7 days) or keeping them across a restart.
  • Choosing which modules or people the demo company has. Use ok init with a blueprint for that.
  • Money in agent answer tables is shown in cents, not formatted as in Brain.

For developers#

The command line on the demo#

Stop the server first: a command opens the same state file and writes it when it finishes. Then name the file and a person:

sh
ok --state orchkernel-demo/state.db --as ada module list
ok --state orchkernel-demo/state.db --as maya brain query tickets
ok --state orchkernel-demo/state.db --as ada runs
ok --state orchkernel-demo/state.db replay --run <run-id>

module list prints one line per module (support-ops enabled ok bundled Support operations); runs lists each run's id, state, agent, steps and cost, which gives you the id for replay.

orchkernel-demo/plans/ holds the walkthrough's plans as JSON (follow-up.json, leads.json, tickets.json). In developer mode (add ?dev=1 to the workspace address) a conversation has an Explicit plan button where you can paste one; ok ask --plan <file> takes one too.

The API#

Every printed token works as a bearer token against /api:

sh
curl -s -H "Authorization: Bearer $MAYA_TOKEN" \
  -H 'content-type: application/json' -d '{}' \
  http://127.0.0.1:8080/api/brain/collections/tickets/query

returns Maya's five tickets as JSON; the same call with Ada's token answers 403 with {"error":"denied","message":"brain: access denied: ada may not read tickets"}.

Asking a paused module's agent through the API (POST /api/threads/<id>/ask with {"agent":"churn-watcher","text":"..."}) answers 403 denied: "policy denied run: kill switch engaged: support-ops is paused". The message and its task are still recorded in the conversation, though, and the task runs as soon as the module is resumed.

GET /api/health answers {"dev_auth":false,"ok":true}, with dev_auth: true when the server was started with --dev-auth. See the CLI and API reference.