Skip to content

Commit a641d84

Browse files
Cookbook preview: OpenHands/enterprise-cookbook#9 (do not merge)
Preview of the Cookbook pages produced by OpenHands/enterprise-cookbook#9 (Skip docs sync pushes when nothing changed), rendered from OpenHands/enterprise-cookbook@f00d868. **Do not merge.** This draft exists only to get a Mintlify preview. It is updated on every push to the source PR and closed when that PR closes. Merged changes reach the docs through a separate `cookbook-sync` PR. _Opened automatically by the docs-preview workflow in OpenHands/enterprise-cookbook._
1 parent 70d6f25 commit a641d84

3 files changed

Lines changed: 172 additions & 0 deletions

File tree

‎cookbook/conversation-tags.mdx‎

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
title: Conversation tags
3+
description: Attach key-value metadata to a conversation with tags and read it back from AppConversation.tags.
4+
icon: tags
5+
---
6+
7+
{/* GENERATED from OpenHands/enterprise-cookbook@f00d8684783a6f687ee209454155e98556b4d0bd (conversation-tags/README.md). Edit the source, not this file. */}
8+
9+
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/f00d8684783a6f687ee209454155e98556b4d0bd/conversation-tags" horizontal />
10+
11+
Stash your own key-value metadata on an OpenHands conversation — for example an
12+
external `environment_url` or `environment_conversation_id` — and read it back
13+
later from your own tooling. Conversations expose a free-form **`tags`** map for
14+
exactly this.
15+
16+
This is the supported replacement for adding a bespoke field (e.g. a custom
17+
`environment_url` column) to the conversation model: use `tags` instead.
18+
19+
## The two-server split
20+
21+
OpenHands has a **Cloud app server** (manages accounts, sandboxes, and
22+
conversations) and, for each sandbox, an **agent server** (the runtime that owns
23+
the conversation). Tags live on the agent-side conversation, and their values
24+
surface on the Cloud's `AppConversation.tags` field.
25+
26+
| Step | Server | Call |
27+
| ----------------------- | --------- | ------------------------------------------------- |
28+
| Start a conversation | Cloud | `POST /api/v1/app-conversations` |
29+
| Resolve agent URL + key | Cloud | `GET /api/v1/app-conversations?ids=<id>` |
30+
| **Write tags** | **Agent** | `PATCH {conversation_url}` with `{"tags": {...}}` |
31+
| Read tags back | Cloud | `GET /api/v1/app-conversations?ids=<id>` → `tags` |
32+
33+
Auth uses `X-Session-API-Key` on both servers, but with **different keys**:
34+
35+
- Cloud app server → your `OH_API_KEY`
36+
- Agent server → the per-conversation `session_api_key` returned by the Cloud
37+
38+
`conversation_url` from the Cloud is already the full agent resource URL
39+
`https://<agent-host>/api/conversations/<id>`, so you `PATCH` it directly.
40+
41+
**Consistency:** the agent server is authoritative and reflects a `PATCH`
42+
immediately (`GET {conversation_url}` → `tags`). The Cloud's
43+
`AppConversation.tags` view is **eventually consistent** — it typically catches
44+
up within a few seconds — so this example confirms the write on the agent server
45+
and then *polls* the Cloud read instead of reading once.
46+
47+
> Why not set tags on the Cloud create call? The Cloud
48+
> `POST/PATCH /api/v1/app-conversations` payloads do not expose `tags` today —
49+
> the agent server is the authoritative place to write them, and the Cloud
50+
> reflects the result. The agent `POST /api/conversations` also accepts `tags`
51+
> at creation time if you provision the sandbox yourself (see
52+
> [`clone-and-attach`](https://github.com/OpenHands/enterprise-cookbook/tree/f00d8684783a6f687ee209454155e98556b4d0bd/clone-and-attach)).
53+
54+
## Tag rules
55+
56+
The agent server enforces:
57+
58+
- **keys** must be **lowercase alphanumeric** — no `_` or `-`
59+
(use `environmenturl`, not `environment_url`; an invalid key is rejected)
60+
- **values** are arbitrary strings, **≤ 256 characters**
61+
- `PATCH` **replaces all** tags — so this example does a read-modify-write to
62+
merge instead of clobbering existing tags
63+
64+
Need to store something structured or longer than 256 chars? Put a JSON string
65+
into a single tag value (within the limit), or split across multiple keys.
66+
67+
## Run it
68+
69+
```bash
70+
export OH_API_KEY=... # your https://app.all-hands.dev API key
71+
pip install requests
72+
73+
# Zero-config: starts a conversation, sets two demo tags, reads them back,
74+
# then deletes the conversation + sandbox.
75+
python tag_conversation.py
76+
```
77+
78+
Sample output:
79+
80+
```text
81+
=== start conversation ===
82+
start-task status: STARTING_CONVERSATION
83+
start-task status: READY
84+
conversation: b07894c6643c453e9091414056ba4828
85+
sandbox status: RUNNING
86+
agent conversation_url: https://qplbjkyptdumixsu.prod-runtime.all-hands.dev/api/conversations/b07894c6643c453e9091414056ba4828
87+
88+
=== set tags (agent server) ===
89+
existing tags: {}
90+
setting tags: {'environmenturl': 'https://env.example.com/session/abc123', 'environmentconversationid': 'ext-0001'}
91+
agent tags (authoritative): {'environmenturl': 'https://env.example.com/session/abc123', 'environmentconversationid': 'ext-0001'}
92+
93+
=== read tags back (cloud server, eventually consistent) ===
94+
AppConversation.tags: {'environmenturl': 'https://env.example.com/session/abc123', 'environmentconversationid': 'ext-0001'}
95+
96+
round-trip OK: True
97+
98+
=== cleanup ===
99+
deleted conversation b07894c6643c453e9091414056ba4828
100+
deleted sandbox 3NjFZz5JDyIVUdvxNsXi0R
101+
```
102+
103+
## Set your own tags
104+
105+
Pass `--tag KEY=VALUE` (repeatable), and `--keep` to leave the conversation open
106+
so you can inspect the tags in the UI:
107+
108+
```bash
109+
python tag_conversation.py \
110+
--tag environmenturl=https://env.example.com/abc \
111+
--tag environmentconversationid=ext-42 \
112+
--keep
113+
```
114+
115+
| Flag | Env var | Default | Purpose |
116+
| ---------------- | ----------------- | --------------------------- | ------------------------------------- |
117+
| `--api-key` | `OH_API_KEY` | — (required) | Cloud API key |
118+
| `--base-url` | `OH_API_BASE` | `https://app.all-hands.dev` | Cloud app server |
119+
| `--tag` | — | two demo tags | `KEY=VALUE`, repeatable |
120+
| `--message` | `INITIAL_MESSAGE` | a hello prompt | First message to the agent |
121+
| `--sandbox-id` | `SANDBOX_ID` | none | Reuse a RUNNING sandbox |
122+
| `--keep` | — | off | Don't delete the conversation/sandbox |
123+
| `--poll-timeout` | `POLL_TIMEOUT` | `240` | Seconds to wait for readiness |
124+
125+
## API endpoints used
126+
127+
| Endpoint | Server | Purpose |
128+
| ------------------------------------------------ | ------ | ---------------------------------------------------------- |
129+
| `POST /api/v1/app-conversations` | Cloud | Start a conversation |
130+
| `GET /api/v1/app-conversations/start-tasks?ids=` | Cloud | Poll for the conversation id |
131+
| `GET /api/v1/app-conversations?ids=` | Cloud | Resolve `conversation_url`, `session_api_key`, read `tags` |
132+
| `GET {conversation_url}` | Agent | Read current tags before merging |
133+
| `PATCH {conversation_url}` | Agent | Set the (merged) tags |
134+
| `DELETE /api/v1/app-conversations/{id}` | Cloud | Clean up the conversation |
135+
| `DELETE /api/v1/sandboxes/{id}?sandbox_id=` | Cloud | Clean up the sandbox |

‎cookbook/index.mdx‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Cookbook
3+
description: Runnable examples for building on the OpenHands API.
4+
---
5+
6+
{/* GENERATED from OpenHands/enterprise-cookbook@f00d8684783a6f687ee209454155e98556b4d0bd (cookbook.yaml). Edit the source, not this file. */}
7+
8+
Standalone, runnable examples for the OpenHands API. Each page is generated from an
9+
example in [OpenHands/enterprise-cookbook](https://github.com/OpenHands/enterprise-cookbook),
10+
where you will find the full source.
11+
12+
## Conversation monitoring & reacting
13+
14+
Observe conversations and react to their state.
15+
16+
<CardGroup cols={2}>
17+
<Card title="Conversation tags" icon="tags" href="/cookbook/conversation-tags">
18+
Attach key-value metadata to a conversation with tags and read it back from AppConversation.tags.
19+
</Card>
20+
</CardGroup>

‎docs.json‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,23 @@
628628
]
629629
}
630630
]
631+
},
632+
{
633+
"tab": "Cookbook",
634+
"groups": [
635+
{
636+
"group": "Overview",
637+
"pages": [
638+
"cookbook/index"
639+
]
640+
},
641+
{
642+
"group": "Conversation monitoring & reacting",
643+
"pages": [
644+
"cookbook/conversation-tags"
645+
]
646+
}
647+
]
631648
}
632649
]
633650
},

0 commit comments

Comments
 (0)