First run
The console's first-run screen: the key shown once, the four .env lines, the language snippets, and the listener that follows your first two runs.
On the first sign-in of a new organisation the console creates a project (first-project, in the region inferred from your request; the name can be changed from the project's Settings, the region only by creating another project), mints its first API key, and opens the screen below. The goal of the screen is one injected lesson: run one records a correction, run two starts with it. Nothing on this screen asks you to fill in a form first.
The screen
Two columns. Left: the key, the .env lines, a language picker and the snippet. Right: the listener.
Your project is ready for its first run
Region EU · project first-project [Rename] [Change region]
API key (shown once)
mbt_xxxx…xxxx [Copy]
Store it as MUBIT_API_KEY. It is not shown again; if you lose it,
create another under Project Settings, API keys.
Pick how you want to run it
[ Python ] [ Node ] [ Coding agent prompt ] [ Try without an LLM (experimental) ] [ curl ]The key is shown once. Copy the four .env lines as one block; the SDK, the CLI and the console read the same values:
MUBIT_API_KEY="mbt_<instance>_<key_id>_<secret>"
MUBIT_ENDPOINT="https://api.mubit.ai"
MUBIT_PROJECT="first-project"
MUBIT_ENV="dev"Under the snippet: "Run it twice. Run 1 ends with a correction. Run 2 starts with that correction injected, so the answer is right on the first try. Watch the panel on the right."
| Tab | What you get |
|---|---|
| Python | mubit.init(agent=...) + mubit.wrap_openai(...); the two-run script from the Quickstart with project, env and agent filled in |
| Node | mubit.init({ agentId }) + mubit.wrapOpenAI(...); the same two runs |
| Coding agent prompt | A prompt to paste into a coding agent: install the SDK, call mubit.init() at startup, wrap the main task in mubit.run("<task>"), call mubit.outcome(good=...) when the result is known, run twice and report whether the second prompt contained a <memory_context> block |
| Try without an LLM (experimental) | mubit.remember(..., kind="lesson", visibility="global") in run one and mubit.context(...) in run two; produces a real injection receipt without a model call |
| curl | The wire events (run.start, note, outcome, run.end to /v2/loop/events, then /v2/loop/context) with event_id values generated for you |
Secondary actions: Run a sample instead executes the two-run demo server-side in your project, tagged source: "sample", so the listener walks every state before your own code produces them; Skip for now records the skip and opens the project Overview in its waiting-for-data state.
Provisioning does not gate the key or the snippet: while the instance starts, the listener shows "Starting your project · elapsed · usually under 2 min" and you can already copy both.
The listener
The right column polls the project every few seconds and moves through the states below. The same component is the empty state of the Overview, Runs and Lessons tabs until the first injection, so a project that has not run yet always shows where it is.
| State | Condition | What you see |
|---|---|---|
provisioning | instance not ready | "Starting your project · elapsed"; "You can copy the key and snippet now." |
listening | ready, no event yet | pulsing dot · "Listening for your first run" · "Run the snippet on the left. Events show here within seconds." |
listening_slow | listening for more than 60 s | the same, plus the troubleshooting block |
run_too_early | listening slowly after the instance was seen provisioning | the run was probably sent before the instance was ready; "Run it again now" |
scope_mismatch | events arrived, but in another project or environment | the troubleshooting block with the scope cause first; check MUBIT_PROJECT and MUBIT_ENV |
legacy_server | the instance has no /v2/loop | events still arrive; lessons are extracted at run end only |
run_received | first event seen, run not ended | live event list (kind, agent, step, elapsed); "Run 1 · agent · n events"; "Let it finish; the lesson is extracted when the run ends." |
reflecting | run ended, no lesson yet | "Run 1 ended · extracting lessons" with elapsed time and reflections_pending |
no_lesson | reflecting for more than 30 s, or a reflection finished with 0 lessons | "No lesson was extracted from run 1." with the reason the server reported: no outcome recorded; nothing to learn from; policy gate rejected it; or the lesson is waiting for review (gate.mode = propose). Buttons: Add a lesson by hand, Run the sample |
lesson_ready | lesson stored, no injection yet | lesson card ("Lesson 1 · from run … · confidence 0.5 · scope session" + content, Open lesson); "Now run the same script again. The lesson is injected before the first model call." |
injected | a receipt on a run other than run 1 | receipt card ("Injected on run 2 · inj_… · n unit(s) · tokens · policy version"), the run-1 and run-2 answers when the outcomes carry them, Open run 2, See the prompt that was sent; "Done. Continue to your project." |
unknown | the poll failed | the snippet stays; "Listener unavailable · retry"; the page is never blocked |
events_received on GET /v2/loop/status is what flips listening to run_received; it is the same counter mubit status --agent <id> prints, so the console and the CLI agree on whether the first event arrived.
Nothing received after 60 seconds
The listener shows the four usual causes:
- Endpoint:
mubit.init()andClient()default tohttps://api.mubit.ai; the CLI and the deprecatedlearnpath default to a local address. SetMUBIT_ENDPOINTfrom the.envblock, and unset any other value for this test. - Key: the key must start with
mbt_and belong to this project. Create a new key under Settings → API keys. - Environment: lessons are partitioned by environment; run 1 and run 2 must use the same
MUBIT_ENV(devby default). - Legacy mode: if the SDK printed
loop v1 not available, the instance is older than the SDK; events still arrive but lessons are extracted at run end only.
Still nothing: Run the sample instead, or open Troubleshooting and run mubit doctor.
After the first injection
Continue to your project opens the project Overview with a one-time banner "Run 2 was injected with lesson …" linking to the run and to the lesson. From the lesson_ready state, Open lesson opens the lesson drawer; from injected, Open run 2 opens the run with the receipt selected and See the prompt that was sent opens the model.call event with the <memory_context> block highlighted.
Setup checklist
Setup in the sidebar keeps a checklist until the required items are done, then disappears. The first two are completed by the screen above.
| # | Item | Where |
|---|---|---|
| 1 | Get an API key | done on the first-run screen |
| 2 | First lesson injected | done when the listener reaches injected |
| 3 | Record an outcome from your real agent (mubit.outcome(good=...)) | Step-level outcomes |
| 4 | Wrap your production agent (mubit.run around the task; Node mubit.wrapOpenAI(...)) | Quickstart |
| 5 | Set env="prod" and create a production key | Access and API keys |
Optional items (invite a teammate, connect a framework adapter, set up BYOK, create an Agent Card or prompt version, register a skill) can be skipped. Items 1 and 2 are derived from the project's onboarding record; the others are ticked by hand and saved to the project, so the checklist is the same on every machine. Only the "Setup entry is hidden" flag lives in the browser.