Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
// Open in GitHub: provides links to open the current file + line number in GitHub.
"ziyasal.vscode-open-in-github",
// Protocol buffer support.
"zxh404.vscode-proto3",
"drblury.protobuf-vsc",
// Spell checker.
"streetsidesoftware.code-spell-checker",
// Add autotmatic line/comment wrapper.
Expand Down
6 changes: 0 additions & 6 deletions .devcontainer/git_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ git config --global submodule.recurse true
# https://stackoverflow.com/questions/27417656/should-diff3-be-default-conflictstyle-on-git
git config --global merge.conflictstyle diff3

# When force-pushing (e.g. a rebased branch), check that the upstream
# branch is still exactly the way it was when it was last fetched. This
# prevents force-pushes to the same branch from two different machines
# (or developers) from accidentally wiping out the first pushed changes.
git config --global push.forceWithLease true

# Do some extra work to pre-configure GitHub authentication when running
# in a codespace. Skip this for a local devcontainer.
if [[ "${CODESPACES:-}" == "true" ]]; then
Expand Down
22 changes: 16 additions & 6 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,15 @@ jobs:
QUERY="$QUERY except attr(\"tags\",\"flaky\",//tests/...)"
fi

# 4) Run the query and pipe into bazel test.
# 4) Build test targets first so that test execution
# doesn't compete with compilation for I/O.
echo "▶ bazel query: $QUERY"
bazel query "$QUERY" \
| xargs bazel test
TARGETS=$(bazel query "$QUERY")
echo "$TARGETS" | xargs bazel build

# 5) Run tests; all build artifacts are cached so
# this only executes tests.
echo "$TARGETS" | xargs bazel test

build-reboot-documentation:
name: Build Reboot documentation
Expand Down Expand Up @@ -211,7 +216,12 @@ jobs:
QUERY="$QUERY except attr(\"tags\",\"flaky\",//tests/...)"
fi

# 4) Run the query and pipe into bazel test.
# 4) Build test targets first so that test execution
# doesn't compete with compilation for I/O.
echo "▶ bazel query: $QUERY"
bazel query "$QUERY" \
| xargs bazel test
TARGETS=$(bazel query "$QUERY")
echo "$TARGETS" | xargs bazel build

# 5) Run tests; all build artifacts are cached so
# this only executes tests.
echo "$TARGETS" | xargs bazel test
5 changes: 3 additions & 2 deletions bazel/py_test_with_workspace_dir.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ def py_test_with_workspace_dir(
visibility = visibility,
main = main,
tags = tags + [
# Force test to be executed unconditionally. Cached results may be
# old since this test tests more than what's in verstions_test.py.
# Force test to be executed unconditionally. Cached results
# may be old since this test tests things on the filesystem
# that aren't expressable as a Bazel dependency.
"external",
],
)
4 changes: 2 additions & 2 deletions charts/reboot/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: 3.3.2
name: reboot
version: "0.46.0"
version: "1.0.3"
description: Reboot is a programming framework that enables transactional microservices built with the developer in mind.
type: application
keywords:
Expand All @@ -10,4 +10,4 @@ keywords:
- scalable
- reactive
home: https://docs.reboot.dev/
appVersion: "0.46.0"
appVersion: "1.0.3"
22 changes: 16 additions & 6 deletions ci/templates/build_and_test.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,15 @@ jobs:
QUERY="$QUERY except attr(\"tags\",\"flaky\",//tests/...)"
fi

# 4) Run the query and pipe into bazel test.
# 4) Build test targets first so that test execution
# doesn't compete with compilation for I/O.
echo "▶ bazel query: $QUERY"
bazel query "$QUERY" \
| xargs bazel test
TARGETS=$(bazel query "$QUERY")
echo "$TARGETS" | xargs bazel build

# 5) Run tests; all build artifacts are cached so
# this only executes tests.
echo "$TARGETS" | xargs bazel test

build-reboot-documentation:
name: Build Reboot documentation
Expand Down Expand Up @@ -281,7 +286,12 @@ jobs:
QUERY="$QUERY except attr(\"tags\",\"flaky\",//tests/...)"
fi

# 4) Run the query and pipe into bazel test.
# 4) Build test targets first so that test execution
# doesn't compete with compilation for I/O.
echo "▶ bazel query: $QUERY"
bazel query "$QUERY" \
| xargs bazel test
TARGETS=$(bazel query "$QUERY")
echo "$TARGETS" | xargs bazel build

# 5) Run tests; all build artifacts are cached so
# this only executes tests.
echo "$TARGETS" | xargs bazel test
54 changes: 54 additions & 0 deletions documentation/docs/ai_chat_apps/examples.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
# AI Chat App Examples

## `agent-wiki`

[`reboot-dev/reboot-agent-wiki`](https://github.com/reboot-dev/reboot-agent-wiki) - _Python backend, React AI Chat App UIs_

The `agent-wiki` example is a shared knowledge base humans
and AIs can both read from and write to. Users hand in raw
conversation transcripts; a background "librarian" agent
(built with Pydantic AI) progressively distills those
transcripts into a small, well-organized set of markdown
pages linked from the wiki's own markdown body, which
serves as a living table of contents. Humans browse the
result in embedded React UIs.

It demonstrates:

* `UI` methods that render React views (wiki, page,
transcript) inside the AI chat interface.
* A long-running `workflow` method (`Wiki.ingest`) that
acts as a per-wiki background agent, reacting to new
transcripts as they arrive.
* `Transaction`s that atomically create related state
across multiple types (e.g. `User.create_wiki` creates a
`Wiki` and records its ID on the user in one step).
* Cross-state references via `<StateType>:<state_id>` URIs
embedded in markdown, letting the agent build a graph of
pages without a dedicated link table.
* An in-process test suite that exercises the librarian
workflow with a scripted Pydantic AI `FunctionModel`, so
no real Anthropic calls are needed in CI.

## `chick-potle`

[`reboot-dev/reboot-chick-potle`](https://github.com/reboot-dev/reboot-chick-potle) - _Python backend, React AI Chat App UIs_

The `chick-potle` example is a small food-ordering AI Chat
App. The AI calls tools to start an order, browse the menu,
and add or remove items from the cart; humans see two
embedded React UIs — a menu grid and a cart — rendered
alongside the conversation.

It demonstrates:

* `UI` methods that render React views (menu, cart) inside
the AI chat interface.
* The `User` type: auto-constructed per authenticated user,
acting as an entry point that creates a `FoodOrder` via a
`Transaction` (`User.start_order`).
* MCP `Tool`s (`get_menu`, `get_cart`, `add_to_cart`,
`remove_from_cart`) that let the AI drive the order
programmatically.
* Generated React hooks (`useFoodOrder()`) shared between
the menu and cart UIs, so adding an item from one view
immediately updates the other.

## `ai-chat-counter`

_Python backend, React AI Chat App UIs_
Expand Down
19 changes: 11 additions & 8 deletions documentation/docs/ai_chat_apps/get_started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,11 @@ Naming a type \`User\` in your \`API(...)\` is special:
- During development all users of your app are automatically
"authenticated" with the built-in \`Anonymous\` OAuth provider, so every
user of your app gets a \`User\` instance.
- All methods on \`User\` are automatically callable by the AI.
- \`User\` acts as an entry point: its methods create other state
types (like \`Counter\`) whose IDs the AI tracks in its context
window.
- Methods on non-\`User\` types use \`mcp=Tool()\` to be
AI-callable.
- Use \`mcp=Tool()\` on every method you want the AI to call,
including \`User\` methods. Use \`mcp=None\` to hide a method.

`}>

Expand Down Expand Up @@ -147,6 +146,7 @@ api = API(
"the `counter_id`, which is not "
"human-readable but should be passed to "
"future tool calls that need it.",
mcp=Tool(),
),
list_counters=Reader(
request=None,
Expand All @@ -156,6 +156,7 @@ api = API(
"description for each. The `counter_id` "
"is not human-readable, but use it when "
"calling tools that take a `counter_id`.",
mcp=Tool(),
),
),
),
Expand All @@ -173,6 +174,7 @@ api = API(
request=CreateCounterRequest,
response=None,
factory=True,
mcp=None,
),
get=Reader(
request=None,
Expand All @@ -191,6 +193,7 @@ api = API(
description=Reader(
request=None,
response=DescriptionResponse,
mcp=None,
),
),
),
Expand Down Expand Up @@ -241,6 +244,7 @@ and optionally a \`request\`. You access state via
```python
# backend/src/servicers/counter.py
from ai_chat_counter.v1.counter import (
CounterEntry,
CreateCounterRequest,
CreateCounterResponse,
ListCountersResponse,
Expand Down Expand Up @@ -280,7 +284,7 @@ class UserServicer(User.Servicer):
for counter_id in self.state.counter_ids:
response = await Counter.ref(counter_id).description(context)
counters.append(
User.CounterEntry(
CounterEntry(
counter_id=counter_id,
description=response.description,
)
Expand Down Expand Up @@ -699,7 +703,7 @@ dev run --watch=web/dist/**/*.html
dev run --python

# Save state between restarts.
dev run --name=ai-chat-counter
dev run --application-name=ai-chat-counter

# Entrypoint.
dev run --application=backend/src/main.py
Expand Down Expand Up @@ -760,9 +764,8 @@ touch mcp_servers.json
{
"mcpServers": {
"counter-server": {
"type": "streamable-http",
"url": "http://localhost:9991/mcp",
"auth": "oauth"
"useOAuth": true
}
}
}
Expand All @@ -771,7 +774,7 @@ touch mcp_servers.json
<!-- MARKDOWN-AUTO-DOCS:END -->

```sh
npx @mcpjam/inspector@v2.0.4 --config mcp_servers.json --server counter-server
npx @mcpjam/inspector@2.4.0 --config mcp_servers.json --server counter-server
```

</Step>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ After the skill finishes building, it starts the app with
[MCPJam Inspector](https://mcpjam.com):

```sh
npx @mcpjam/inspector@v2.0.4 \
npx @mcpjam/inspector@2.4.0 \
--config mcp_servers.json --server my-app
```

Expand Down
12 changes: 8 additions & 4 deletions documentation/docs/ai_chat_apps/what_is.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ api = API(
"the `counter_id`, which is not "
"human-readable but should be passed to "
"future tool calls that need it.",
mcp=Tool(),
),
list_counters=Reader(
request=None,
Expand All @@ -121,6 +122,7 @@ api = API(
"description for each. The `counter_id` "
"is not human-readable, but use it when "
"calling tools that take a `counter_id`.",
mcp=Tool(),
),
),
),
Expand All @@ -138,6 +140,7 @@ api = API(
request=CreateCounterRequest,
response=None,
factory=True,
mcp=None,
),
get=Reader(
request=None,
Expand All @@ -156,6 +159,7 @@ api = API(
description=Reader(
request=None,
response=DescriptionResponse,
mcp=None,
),
),
),
Expand All @@ -164,10 +168,10 @@ api = API(

<!-- MARKDOWN-AUTO-DOCS:END -->

All methods on `User` are automatically callable by the AI.
Methods on other types (like `Counter`) are exposed with
`mcp=Tool()`. The AI receives the state ID when it creates
a new instance and uses it in subsequent calls.
Use `mcp=Tool()` on every method you want the AI to call,
including `User` methods. Methods on other types (like `Counter`)
that expose `mcp=Tool()` receive a state ID from the AI when it
creates a new instance and uses it in subsequent calls.

Under the hood, AI Chat Apps use [MCP (the Model Context
Protocol)](/learn_more/mcp_apps) — the standard that AI clients use to
Expand Down
11 changes: 2 additions & 9 deletions documentation/docs/deploy_on_reboot_cloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
To deploy your Reboot app to production, you can use the [Reboot Cloud](https://cloud.reboot.dev/). The Reboot Cloud leverages Reboot's safety guarantees to automatically partition and deploy your application across a cluster of machines, providing automatic scaling and high availability!

```console
$ rbt cloud up --image-name=...
$ rbt cloud up --name=my-app --organization=my-org
...
Application starting; your application will be available at:

Expand All @@ -25,11 +25,4 @@ of Reboot Cloud on your own hardware.

## Comparison

| | `rbt serve` (EBS or equivalent)| `rbt serve` (EFS or equivalent)| Reboot Cloud | Reboot Cloud Enterprise |
| :-------------------------------- | :----------------------------- | :----------------------------- | :---------------------------------------------- | :---------------------------------------- |
| Physical backups | yes | yes | yes | yes |
| Replication | within an availability zone | within a region | within a region | within a region |
| High availability (failover time) | \~minutes | \~seconds | \~seconds | \~seconds |
| Vertical scaling | yes | yes | yes | yes |
| Horizontal scaling | no | no | yes | yes |
| Availability | available now | available now | [Join the waitlist](https://cloud.reboot.dev/)! | [Contact Reboot](mailto:team@reboot.dev)! |
For a side-by-side of Reboot Cloud against `rbt serve` on EBS and EFS, see [the deployment comparison on "Deploy on your own"](/deploy_on_your_own#comparison).
Loading
Loading