@opengeni/runtime 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/assets/codemode-client.json +1 -0
  2. package/dist/chunk-4A4XTKKX.js +1 -0
  3. package/dist/{chunk-RIJ6DCYS.js → chunk-5HJEVOMJ.js} +9817 -9494
  4. package/dist/chunk-5HJEVOMJ.js.map +1 -0
  5. package/dist/{chunk-FHGLYLBL.js → chunk-SPT3PLMX.js} +1 -87
  6. package/dist/chunk-SPT3PLMX.js.map +1 -0
  7. package/dist/{chunk-GB763TSV.js → chunk-TE27J65Q.js} +1 -1
  8. package/dist/chunk-TE27J65Q.js.map +1 -0
  9. package/dist/{chunk-46BFUGFL.js → chunk-WIHICNWS.js} +1660 -388
  10. package/dist/chunk-WIHICNWS.js.map +1 -0
  11. package/dist/{chunk-UU6EJR52.js → chunk-YU4VRTR4.js} +2 -2
  12. package/dist/chunk-YU4VRTR4.js.map +1 -0
  13. package/dist/chunk-ZG2YH25H.js +94 -0
  14. package/dist/chunk-ZG2YH25H.js.map +1 -0
  15. package/dist/codex-tool-search.d.ts +5 -4
  16. package/dist/context-compaction.d.ts +19 -0
  17. package/dist/gmail-rest-mcp.js +1 -1
  18. package/dist/index.d.ts +30 -22
  19. package/dist/index.js +25 -5
  20. package/dist/lazy-manifest-OEYEHNVY.js +45 -0
  21. package/dist/lazy-manifest-OEYEHNVY.js.map +1 -0
  22. package/dist/lazy-manifest.d.ts +6 -0
  23. package/dist/lazy-tool-transport.d.ts +3 -2
  24. package/dist/{localSources-PVFCAPN2.js → localSources-TWHTEKGO.js} +3 -2
  25. package/dist/localSources-TWHTEKGO.js.map +1 -0
  26. package/dist/metrics.d.ts +6 -0
  27. package/dist/operational-instructions.d.ts +1 -1
  28. package/dist/prepared-compaction-request.d.ts +8 -0
  29. package/dist/provider-history-adapter.d.ts +2 -2
  30. package/dist/runtime-skills.d.ts +3 -10
  31. package/dist/sandbox/codemode-client.d.ts +17 -0
  32. package/dist/sandbox/codemode-token.d.ts +3 -3
  33. package/dist/sandbox/index.d.ts +2 -1
  34. package/dist/sandbox/index.js +8 -2
  35. package/dist/sandbox/materialization-verification-error.d.ts +27 -0
  36. package/dist/sandbox/provider-command-session.d.ts +44 -2
  37. package/dist/sandbox/providers/modal-command-control.d.ts +32 -29
  38. package/dist/sandbox/providers/modal-command-router-wire.d.ts +49 -0
  39. package/dist/sandbox/providers/modal-command-session.d.ts +2 -1
  40. package/dist/sandbox/providers/modal-legacy-command-control.d.ts +50 -0
  41. package/dist/sandbox/providers/modal-materialization-verification.d.ts +7 -0
  42. package/dist/sandbox/providers/modal.d.ts +0 -8
  43. package/dist/sandbox/routing/routing-session.d.ts +21 -0
  44. package/dist/sandbox/turn-tool-cancellation.d.ts +1 -0
  45. package/dist/skill-library.d.ts +0 -6
  46. package/dist/skill-library.js +1 -1
  47. package/dist/workspace-tool-gateway.js +7 -5
  48. package/package.json +9 -7
  49. package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +19 -0
  50. package/src/bundled_artifact_skills/opengeni-documents/references/api.md +22 -0
  51. package/src/bundled_default_skills/opengeni-client/SKILL.md +349 -0
  52. package/src/bundled_default_skills/opengeni-client/agents/openai.yaml +4 -0
  53. package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +256 -0
  54. package/src/bundled_default_skills/opengeni-client/references/compatibility-and-troubleshooting.md +84 -0
  55. package/src/bundled_default_skills/opengeni-client/references/customer-skill-template.md +96 -0
  56. package/src/bundled_default_skills/opengeni-client/references/data-tools-and-credentials.md +99 -0
  57. package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +81 -0
  58. package/src/bundled_default_skills/opengeni-client/references/external-users-and-connect.md +457 -0
  59. package/src/bundled_default_skills/opengeni-client/references/isolation-and-authorization.md +77 -0
  60. package/src/bundled_default_skills/opengeni-client/references/product-integration-shapes.md +232 -0
  61. package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +116 -0
  62. package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +157 -0
  63. package/src/bundled_default_skills/opengeni-help/SKILL.md +101 -0
  64. package/src/bundled_management_skills/opengeni-skills/SKILL.md +33 -3
  65. package/src/codex-tool-search.ts +13 -5
  66. package/src/context-compaction.ts +87 -4
  67. package/src/gmail-rest-mcp.ts +1 -2
  68. package/src/index.ts +363 -131
  69. package/src/lazy-manifest.ts +55 -0
  70. package/src/lazy-tool-transport.ts +15 -2
  71. package/src/metrics.ts +6 -0
  72. package/src/model-request-capture.ts +3 -0
  73. package/src/operational-instructions.ts +11 -2
  74. package/src/prepared-compaction-request.ts +51 -0
  75. package/src/provider-history-adapter.ts +12 -3
  76. package/src/runtime-skills.ts +3 -17
  77. package/src/sandbox/codemode-client.ts +204 -0
  78. package/src/sandbox/codemode-token.ts +7 -2
  79. package/src/sandbox/index.ts +7 -0
  80. package/src/sandbox/materialization-verification-error.ts +65 -0
  81. package/src/sandbox/provider-command-session.ts +70 -2
  82. package/src/sandbox/providers/modal-command-control.ts +386 -242
  83. package/src/sandbox/providers/modal-command-router-wire.ts +248 -0
  84. package/src/sandbox/providers/modal-command-session.ts +177 -4
  85. package/src/sandbox/providers/modal-legacy-command-control.ts +351 -0
  86. package/src/sandbox/providers/modal-materialization-verification.ts +122 -0
  87. package/src/sandbox/providers/modal.ts +1 -9
  88. package/src/sandbox/routing/routing-session.ts +417 -79
  89. package/src/sandbox/turn-tool-cancellation.ts +38 -2
  90. package/src/skill-catalog.ts +1 -0
  91. package/src/skill-library.ts +0 -6
  92. package/src/workspace-governance.ts +0 -1
  93. package/src/workspace-skills.ts +114 -74
  94. package/dist/chunk-46BFUGFL.js.map +0 -1
  95. package/dist/chunk-FHGLYLBL.js.map +0 -1
  96. package/dist/chunk-GB763TSV.js.map +0 -1
  97. package/dist/chunk-RIJ6DCYS.js.map +0 -1
  98. package/dist/chunk-UU6EJR52.js.map +0 -1
  99. /package/dist/{localSources-PVFCAPN2.js.map → chunk-4A4XTKKX.js.map} +0 -0
@@ -0,0 +1,349 @@
1
+ ---
2
+ name: opengeni-client
3
+ audience: integration-agent
4
+ description: >-
5
+ Integrate OpenGeni capabilities into an external product, website, backend,
6
+ CLI, or automation. Use for discovery, connecting repositories and resources,
7
+ SDK/API and React choices, implementation, verification, and handoff against
8
+ a managed, self-hosted, or local OpenGeni deployment. Not for changing
9
+ OpenGeni internals or mounting its runtime inside the customer's process.
10
+ ---
11
+
12
+ # OpenGeni Client
13
+
14
+ Use this skill when a customer's product and OpenGeni remain separate systems.
15
+ That is the normal integration shape: the product owns its users and business
16
+ UI, while a standalone OpenGeni deployment owns agent sessions and execution.
17
+
18
+ Do not interpret "embed" as "move OpenGeni into the product process." Advanced
19
+ in-process router/core embedding is a separate infrastructure choice. Route that
20
+ work to the repo-maintainer `opengeni` skill and `docs/embedding.md`.
21
+
22
+ Do not confuse two meanings of "skill": this file teaches a customer's coding
23
+ agent how to integrate OpenGeni; session `skills` are runtime capabilities or
24
+ instructions attached to an OpenGeni agent. The former designs the integration.
25
+ The latter is product data sent through the installed SDK contract.
26
+
27
+ Code and the live service are authoritative. Prefer `/v1/config/client`,
28
+ `/v1/access/me`, the installed package types, and live probes over memorized
29
+ route, model, tool, or backend lists. When source is available, verify exact
30
+ behavior in `packages/sdk`, `packages/react`, contracts, and API routes.
31
+ Read `docs/product-integration.md` when the repository is available; it is the
32
+ canonical product boundary for organization keys, workspace mapping, and Skill
33
+ ownership.
34
+
35
+ Without repository access, start at https://docs.opengeni.ai/llms.txt and fetch
36
+ the relevant Markdown pages. Before replacing an AI provider, answering a cost
37
+ question, or reporting a setup blocker, read
38
+ [Compatibility and troubleshooting](references/compatibility-and-troubleshooting.md).
39
+
40
+ ## Work Adaptively
41
+
42
+ This same guide is bundled as `builtin:opengeni-client` in ordinary OpenGeni
43
+ sessions and lives in `.agents/skills/opengeni-client` for external coding agents.
44
+ No Pack, installation, repository clone, or sandbox is needed to read the bundled
45
+ copy. It is guidance, not authority to access a repository, secret, or deployment.
46
+ Embedded products may narrow bundled guidance with `bundledSkillIds`.
47
+
48
+ - Inspect the customer's repository, authentication, tenancy, data routes,
49
+ frontend conventions, installed packages, tests, CI, and deployment guidance
50
+ before asking questions or choosing an integration shape.
51
+ - If the target repository or resources are missing, first inspect available
52
+ authorized resources and connection/setup tools. Help the user connect or
53
+ attach the specific missing source; explain the next action in product terms.
54
+ Continue useful discovery without requesting broad credentials or pretending
55
+ missing access is configured. Read
56
+ [Discovery and autonomy](references/discovery-and-autonomy.md) for that workflow.
57
+ - Ask only for consequential product choices or external authority that cannot
58
+ be inferred. Do not ask the customer to restate facts the system proves.
59
+ - Use a reversible, clearly stated default when an unresolved choice is
60
+ low-risk. Resolve privacy, tenant authority, data writes, cost exposure, and
61
+ ambiguous external mutations before crossing those boundaries.
62
+ - Match the requested delivery autonomy. Repository or cloud access is
63
+ technical capability, not permission to push, deploy, merge, or change
64
+ production.
65
+ - This Skill guides an implementation agent. Never copy it into the runtime
66
+ Skills of the customer-facing agent.
67
+
68
+ ## Choose the product experience before the transport
69
+
70
+ Read [Product shapes and UI](references/product-shapes-and-ui.md) when adding
71
+ or changing a user-facing surface. Preserve a suitable existing interface;
72
+ for new React chat, evaluate the packaged components and headless hooks before
73
+ writing replacements. The chat facade below serves compatible/custom clients;
74
+ packaged React conversation components use the normal session SDK and authenticated
75
+ proxy routes. Choose the combination that fits the product, not the shortest snippet.
76
+
77
+ Read [Integration configuration and verification](references/runtime-profile-and-verification.md)
78
+ when defining agent behavior or verifying delivery. Use representative product
79
+ questions to check useful answers and actual tool execution, not just connectivity.
80
+
81
+ ## Chat facade: `@opengeni/sdk/chat`
82
+
83
+ When using `user`, first provision that user's approved workspace membership
84
+ through the explicit onboarding flow in `references/external-users-and-connect.md`.
85
+ The facade uses `asUser()` and never grants or restores membership on a chat
86
+ request. An existing tenant is not proof that this user belongs to it. For shared
87
+ conversations use the same OpenGeni session ID; identity changes authority, not
88
+ the conversation address. Use `chatBySessionId` to reopen historical sessions
89
+ whose IDs were derived with the old user-namespaced helper.
90
+
91
+ Use this when the chosen frontend speaks one of the supported chat protocols
92
+ and OpenGeni should sit behind it. Install, keep the organization API key on the
93
+ server, and put one handler behind the chat endpoint:
94
+
95
+ ```bash
96
+ bun add @opengeni/sdk
97
+ ```
98
+
99
+ ```ts
100
+ import { OpenGeni, createChatHandler } from "@opengeni/sdk/chat";
101
+
102
+ const og = new OpenGeni({
103
+ apiKey: process.env.OPENGENI_API_KEY!,
104
+ organizationId: process.env.OPENGENI_ORGANIZATION_ID!,
105
+ });
106
+
107
+ export const POST = createChatHandler(og, {
108
+ // Your auth hook. Tenant and user come from the authenticated request, never the body.
109
+ resolve: async (request) => {
110
+ const me = await authenticate(request);
111
+ return me ? { tenant: me.accountId, user: me.userId } : new Response("Unauthorized", { status: 401 });
112
+ },
113
+ // format: "vercel" keeps an existing useChat client; "openai-chat" / "openai-responses"
114
+ // keep an OpenAI-shaped client. The default streams native chunks for custom clients.
115
+ });
116
+
117
+ // Server-side use without an endpoint:
118
+ const chat = await og.chat({ tenant: "acme", user: "u_42", conversation: "c_9" });
119
+ const reply = await chat.send("hello"); // reply.text; chat.stream(...) yields chunks
120
+ ```
121
+
122
+ Browser: use a custom or compatible frontend for the backend chat handler.
123
+ For native OpenGeni React UI, install `@opengeni/react` and use
124
+ `SessionConversation` or compose `MessageTimeline` and `ChatComposer` with
125
+ the normal SDK and authenticated session routes. Reset private UI state and cancel old
126
+ requests when the authenticated user or tenant changes. Every customer gets one workspace (`tenant`), every
127
+ conversation one deterministic session, and each session picks its own
128
+ isolation. Conversation IDs are independent of the acting user; ordinary API
129
+ authorization decides who can use the same shared conversation. Without a `user`,
130
+ `resolve` must return the `conversation` itself. The Vercel and OpenAI adapters
131
+ send only the latest user message and import earlier messages once as context
132
+ on the first message; afterwards OpenGeni owns the history.
133
+
134
+ | Scenario | `agentAccess` | `memory` |
135
+ | --- | --- | --- |
136
+ | Support desk: agent confined to its chat tree | `"session"` (default) | `false` (default) |
137
+ | Agents restricted to their canonical user's chats | `"user"` with `asUser()` | `"user"` |
138
+ | A team collaborating across chats | `"workspace"` | `"workspace"` |
139
+ | Any of the above with Knowledge authoring initially Off | any | `false` |
140
+
141
+ `agentAccess` is enforced in the server-side session-authorization seam for
142
+ agents as outbound task scope: own tree, same canonical user, or workspace.
143
+ A narrow target remains reachable by an authorized broad coordinator; target
144
+ private visibility and normal permissions still apply. `asUser()` establishes
145
+ canonical authority, not a second end-user label. Graduate to `og.client`
146
+ (`OpenGeniClient`) on the same `chat.sessionId` when the product needs files,
147
+ tools, approval policies, forks, or realtime voice. The
148
+ `examples/chat-quickstart` directory provides a backend-only server example.
149
+
150
+ ## Choose The Integration Shape First
151
+
152
+ Pick the smallest surface that satisfies the product:
153
+
154
+ 1. **Stock OpenGeni handoff** — link or deep-link into the OpenGeni web app.
155
+ The product keeps no agent UI.
156
+ 2. **Headless product integration** — the product backend uses
157
+ `@opengeni/sdk`; the product renders its own UI and exposes tenant-scoped,
158
+ same-origin routes to its browser or mobile client.
159
+ 3. **React session integration** — compose `@opengeni/react/session` hooks and
160
+ pure projections into the product's UI. Add styled subpaths only for the
161
+ surfaces the product wants.
162
+ 4. **OpenGeni-rendered React experience** — mount the packaged composer,
163
+ timeline, realtime, or session chrome and import
164
+ `@opengeni/react/compiled.css` once. No Tailwind setup or source scan is
165
+ required. Override `--og-*` tokens only when branding is wanted.
166
+ 5. **Workbench integration** — mount the optional Changes/Files/Terminal/Desktop
167
+ workspace when the product genuinely exposes agent compute. It has optional
168
+ heavy peers and is not required for ordinary chat/session integration.
169
+
170
+ Read `references/product-integration-shapes.md` before designing the boundary.
171
+ Read `references/api-workflows.md` for session, upload, retry, repository,
172
+ machine, and schedule patterns.
173
+
174
+ For deeper implementation decisions, read selectively:
175
+
176
+ - [Discovery and autonomy](references/discovery-and-autonomy.md)
177
+ - [Isolation and authorization](references/isolation-and-authorization.md)
178
+ - [Product shapes and UI](references/product-shapes-and-ui.md)
179
+ - [Data tools and credentials](references/data-tools-and-credentials.md)
180
+ - [Integration configuration and verification](references/runtime-profile-and-verification.md)
181
+ - [External users and embedded connection setup](references/external-users-and-connect.md)
182
+
183
+ This tree is the canonical developer guide for product integration. It does not define a runtime
184
+ profile API, schedule Skill fields, or a new registry. Any references to an
185
+ integration's "runtime profile" mean configuration owned by the customer's code,
186
+ not a new OpenGeni resource. Use this Skill for a coding session, not an end-user
187
+ runtime session.
188
+
189
+ ## Choose The Credential
190
+
191
+ - Use an **organization API key** when one server-side product integration
192
+ provisions or manages many organization workspaces in one OpenGeni
193
+ organization.
194
+ - Use a **workspace API key** when the integration is deliberately constrained
195
+ to one organization workspace and should not provision others.
196
+ - Use a **delegated token** when the host acts with short-lived, explicit
197
+ user/workspace authority rather than one standing product credential.
198
+ - A **deployment access key** is a coarse deployment perimeter. Never use it as
199
+ tenant identity or infer organization/workspace authority from it.
200
+
201
+ ## Default Trust Boundary
202
+
203
+ - Keep the organization API key and operator credentials on the product server.
204
+ - Authenticate the product's user first, resolve their allowed OpenGeni
205
+ workspace/session server-side, and expose only the routes that product needs.
206
+ - Use `@opengeni/sdk` instead of reconstructing event streaming, upload signing,
207
+ retries, or wire types by hand.
208
+ - Use `proxySessionEventStream` for a same-origin browser SSE route. Structural
209
+ React client types let a host implement only the methods its mounted hooks use.
210
+ - Direct browser access is valid only when the deployment's normal browser auth
211
+ or an explicitly accepted bearer/CORS design makes it safe. Never ship a
212
+ privileged shared API key in a browser bundle.
213
+
214
+ The product owns external identity, tenant-to-workspace mapping, business
215
+ entities, navigation, presentation, and product-specific admission. OpenGeni
216
+ owns sessions, turns, durable event history, approvals, agent execution,
217
+ selected tools/resources, files, realtime session state, and compute lifecycle.
218
+ Link records by opaque IDs; do not copy one system's whole data model into the
219
+ other.
220
+
221
+ ## Organization And Workspace Bootstrap
222
+
223
+ Use one organization API key for the external backend. Organization key
224
+ administration is exposed through `listOrganizationApiKeys`,
225
+ `createOrganizationApiKey`, and `deleteOrganizationApiKey`, corresponding to
226
+ the organization-scoped `/v1/organizations/:organizationId/api-keys` routes.
227
+ The create response shows the token once; store it only in the product's secret
228
+ manager.
229
+
230
+ For each chosen product sharing boundary, call `ensureWorkspace` /
231
+ `PUT /v1/workspaces/external` with a stable external mapping identity and persist
232
+ the returned `result.workspace.id`; `result.created` distinguishes the first
233
+ insert from an idempotent replay. Call it an **organization workspace** in
234
+ customer guidance; its exact wire kind is `"shared"`. Personal workspaces are
235
+ excluded and must never be selected through a default-workspace fallback.
236
+
237
+ Choose the workspace from who shares documents, workspace instructions,
238
+ Connections, and integrations: normally one workspace per customer. Chat
239
+ human visibility is controlled by `visibility`, not by `agentAccess` or Knowledge.
240
+ Use `asUser(externalId)` for the authenticated product user. The server derives
241
+ the canonical user; never supply an `endUser` label as authority. Separately,
242
+ `agentAccess: "session" | "user" | "workspace"` controls cross-session agent
243
+ reach. Compatibility `memoryScope: "workspace" | "user" | "off"` selects Knowledge
244
+ authoring scope, not transcript visibility. Off initializes authoring to Off;
245
+ existing authorized Knowledge remains retrievable. Personal Knowledge belongs
246
+ to the verified user of the active
247
+ turn, including when different users collaborate in one shared session. Use
248
+ existing task notes for temporary session-tree coordination; there is no active
249
+ session Memory scope. Use a separate workspace when groups need different
250
+ Connections, integrations, or instructions.
251
+
252
+ Unscoped organization-key-created top-level sessions are workspace-visible.
253
+ For product-user ownership, use the server-side `asUser(externalId)` client and
254
+ explicit workspace membership described in `references/external-users-and-connect.md`;
255
+ verified external owners can create private sessions when the organization enables
256
+ that feature. Private sessions do not make workspace Files or Sites private.
257
+ Managed-human Only-me sessions are not a backend impersonation mechanism. A live
258
+ agent with cross-session tools can reach unrelated sessions only when its
259
+ outbound `agentAccess` scope and ordinary resource authorization allow it.
260
+ The target's `agentAccess` never restricts inbound access; private-session
261
+ ownership and ordinary permissions still apply.
262
+ Removing tools is not a substitute for private human visibility.
263
+
264
+ The external backend owns product Skills. Store and version them outside
265
+ OpenGeni, then pass the selected definitions inline in
266
+ `CreateSessionRequest.skills` for each product-created session. There is no
267
+ organization-wide Skill registry or Skill inheritance in this integration
268
+ contract.
269
+
270
+ Use `CreateSessionRequest.bundledSkillIds` to narrow OpenGeni's bundled guidance
271
+ independently: omitted means defaults, `[]` means none, and explicit IDs such as
272
+ `builtin:opengeni-documents` allow only those whose normal inclusion rules hold.
273
+ Children inherit and can only narrow; scheduled-task `agentConfig` and automation
274
+ `sessionTemplate` accept the same field. This does not hide workspace or inline
275
+ Skills, grant tools, or disable eager `skill_read`. Keep the selection stable on
276
+ keyed-create retries. Never try to control it through arbitrary session metadata.
277
+
278
+ New Skill inputs require valid `SKILL.md` frontmatter, which owns the name and
279
+ description. Do not replay old headerless Skills as new session input.
280
+
281
+ ## Prompt And Context Contract
282
+
283
+ Use each prompt surface for its exact authority and lifetime:
284
+
285
+ - Workspace `agentInstructions`: stable workspace-wide system persona and behavior.
286
+ - Session `instructions`: durable system-level agent refinement for one session.
287
+ - `modelContext`: ordinary model-visible content attached to one exact user
288
+ message as a separate history part; standard timeline rendering omits it.
289
+ - `initialMessage` and later message text: the visible part of that user message.
290
+
291
+ `modelContext` is not secret, private, or privileged; full event/audit reads may
292
+ return it. Do not hide business facts in a snapshot when the agent should inspect
293
+ them with an authorized product MCP tool. Prefer concise message context plus
294
+ canonical tool access. Changing `modelContext` must not change the persistent
295
+ agent instruction prefix.
296
+
297
+ ## Client Workflow
298
+
299
+ 1. Resolve the API base URL and load the server-held organization API key.
300
+ 2. Resolve the authenticated product tenant, call `ensureWorkspace` with its
301
+ stable external identity, and persist or verify the opaque workspace mapping.
302
+ 3. Read client config and access context without falling back to a Personal
303
+ workspace.
304
+ 4. Load the exact Skills selected by the external product and pass them inline.
305
+ 5. Create a session with a stable idempotency key; optionally preallocate its ID
306
+ when the product must persist a link before the first turn can run.
307
+ 6. Attach only canonical resources and an explicit minimal tool selection the
308
+ user may use. Omitting tool selections inherits workspace/deployment
309
+ defaults, including first-party workspace and cross-session capabilities.
310
+ 7. Stream/replay session events through the SDK; tolerate unknown additive event
311
+ types.
312
+ 8. Send visible text separately from `modelContext`.
313
+ 9. Use the SDK upload helper; it owns begin, signed storage PUT, and completion.
314
+ 10. Surface approvals, human-input requests, queue state, errors, credit limits,
315
+ and reconnect state as product state rather than generic chat text.
316
+ 11. Add realtime, Connected Machines, schedules, or the workbench only when the
317
+ product use case needs them.
318
+
319
+ ## Guardrails
320
+
321
+ - Workspace-scoped routes are canonical; resource IDs never authorize by
322
+ themselves.
323
+ - Organization workspaces have wire `kind: "shared"`; Personal workspaces are
324
+ outside the external product mapping.
325
+ - Use one workspace per customer and private/shared visibility for human
326
+ access. Knowledge settings and prompt instructions do not create a tenant boundary.
327
+ `agentAccess` optionally restricts agent reach further; tool removal is
328
+ defense in depth, not a replacement for authorization.
329
+ - Use separate workspaces only when groups must not share documents,
330
+ Connections, integrations, or workspace instructions.
331
+ - Do not invent an organization-wide Skill registry or rely on Skill
332
+ inheritance. The external backend passes selected Skills inline per session.
333
+ - The SDK cannot accept arbitrary customer backend functions as remote tools.
334
+ Expose an existing API through a reviewed OpenAPI/GraphQL Integration or an
335
+ MCP server.
336
+ - OpenGeni's credential broker encrypts secrets and keeps them out of model
337
+ context, but the trusted control plane can decrypt them for the authorized
338
+ provider request. Do not describe it as zero knowledge.
339
+ - Do not call Temporal, NATS, Postgres, workers, sandbox providers, object
340
+ storage APIs, or MCP transports as substitutes for the public SDK/API.
341
+ - Do not claim auth, model, tool, billing, CORS, storage, or compute behavior
342
+ until the live deployment or current source proves it.
343
+ - Keep examples generic and parameterized. Skills may name non-secret origins
344
+ and conventions, but credentials come from a secret manager or environment.
345
+ - Generate a customer-specific skill only for stable facts their coding agents
346
+ repeatedly need. Keep it beside their integration code, point it at the SDK,
347
+ include a config/access smoke probe, and never paste secrets into it.
348
+ Start from `references/customer-skill-template.md` when the OpenGeni skill
349
+ package is available.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "OpenGeni Client"
3
+ short_description: "Developer guide for tenant-safe OpenGeni SDK and UI integration; not runtime instructions."
4
+ default_prompt: "Integrate my product with OpenGeni using the smallest safe surface. Keep standing credentials server-side, choose organization vs workspace key vs delegated token explicitly, map each external tenant to an organization workspace without Personal-workspace fallback, and pass product-owned Skills inline per session."
@@ -0,0 +1,256 @@
1
+ # OpenGeni API Workflows
2
+
3
+ This reference is intentionally pattern-level. Check the live service or source
4
+ contracts for exact schemas before generating SDK code. When the repository is
5
+ available, `docs/product-integration.md` is the canonical organization-key,
6
+ workspace-mapping, and Skill-ownership guide.
7
+
8
+ ## Access Setup
9
+
10
+ Choose one credential deliberately:
11
+
12
+ - Managed SaaS product integration: create an organization API key through
13
+ `POST /v1/organizations/:organizationId/api-keys` /
14
+ `createOrganizationApiKey`, store the one-time token on the product server,
15
+ and send `Authorization: Bearer <api-key>`.
16
+ - One-workspace automation: use a workspace API key and do not call
17
+ organization provisioning routes.
18
+ - User/workspace delegation: use a short-lived delegated token with explicit
19
+ authority rather than a standing organization key.
20
+ - Configured/self-hosted perimeter: a deployment access key may gate the
21
+ deployment, but it is not tenant identity.
22
+ - Local development: the service may resolve a default dev subject/workspace without external auth.
23
+
24
+ Only add `x-opengeni-access-key` when the operator says the deployment
25
+ shared-key boundary is enabled. It is not a replacement for organization API
26
+ keys in managed SaaS.
27
+
28
+ ## Minimal Server-Side Session Client
29
+
30
+ ```ts
31
+ import { OpenGeniClient } from "@opengeni/sdk";
32
+
33
+ const client = new OpenGeniClient({
34
+ baseUrl: process.env.OPENGENI_API_BASE_URL!,
35
+ apiKey: process.env.OPENGENI_ORGANIZATION_API_KEY!,
36
+ });
37
+
38
+ const organizationId = process.env.OPENGENI_ORGANIZATION_ID!;
39
+ const { workspace } = await client.ensureWorkspace({
40
+ accountId: organizationId,
41
+ externalSource: "acme-product",
42
+ externalId: productTenant.id,
43
+ name: productTenant.displayName,
44
+ });
45
+ if (workspace.kind !== "shared") {
46
+ throw new Error("Product integrations require an organization workspace");
47
+ }
48
+
49
+ const skills = await productSkillStore.resolveForSession(productTenant.id);
50
+ const created = await client.createSession(workspace.id, {
51
+ initialMessage: "Inspect the uploaded logs and summarize the failing deploy step.",
52
+ idempotencyKey: crypto.randomUUID(),
53
+ skills,
54
+ firstPartyMcpTools: selectedFirstPartyTools,
55
+ tools: selectedIntegrationServers,
56
+ });
57
+
58
+ for await (const event of client.streamEvents(workspace.id, created.id)) {
59
+ if (event.type === "agent.message.delta") {
60
+ process.stdout.write((event.payload as { text?: string }).text ?? "");
61
+ }
62
+ }
63
+ ```
64
+
65
+ This code belongs on the product server, not in a browser bundle. For a browser
66
+ timeline, expose a tenant-scoped same-origin route and use the SDK's
67
+ `proxySessionEventStream` helper. Authenticate the product user and resolve the
68
+ allowed workspace/session before opening the upstream stream.
69
+
70
+ `ensureWorkspace` maps through `PUT /v1/workspaces/external`. Use a stable
71
+ external source/id pair and persist the returned opaque id. The returned
72
+ organization workspace has wire `kind: "shared"`. Personal workspaces are
73
+ excluded; do not fall back to `/v1/access/me`'s default/personal workspace.
74
+ The method returns `{ workspace, created }`; use `workspace.id`, and treat
75
+ `created: false` as the normal idempotent replay result.
76
+
77
+ The product backend stores and versions Skills outside OpenGeni and passes the
78
+ selected definitions inline in `CreateSessionRequest.skills`. There is no
79
+ organization-wide Skill registry or Skill inheritance in this integration
80
+ contract.
81
+
82
+ The product must choose the workspace mapping from its sharing rule before
83
+ running this flow. A tenant-shared workspace is suitable only when that tenant
84
+ may share workspace-scoped agent authority and resources. Use a per-user
85
+ workspace for cross-user chat privacy and a per-chat workspace for hard
86
+ same-user chat isolation. Knowledge authoring Off does not create either
87
+ boundary.
88
+
89
+ For a headless product, send an explicit minimal `firstPartyMcpTools` and
90
+ `tools` selection. Omission inherits deployment/workspace defaults. Removing
91
+ cross-session tools from a shared workspace is defense in depth, not a hard
92
+ tenant boundary.
93
+
94
+ ## Existing APIs As Agent Tools
95
+
96
+ The SDK cannot serialize ordinary customer backend functions into tools. Use
97
+ one of the supported network boundaries:
98
+
99
+ - For an existing HTTP API, host a focused OpenAPI 3.0/3.1 document and call
100
+ `previewApiIntegration`, then `installApiIntegration` with the exact revision,
101
+ digest, Connection, stable instance key, and selected operations.
102
+ - For GraphQL, use the same preview/install lifecycle with the GraphQL source.
103
+ - For MCP, install a workspace capability or pass a session-specific
104
+ `mcpServers` definition with an HTTPS URL, allowed tools, approval policy, and
105
+ write-only headers or a `connectionRef`.
106
+
107
+ Preview/install is deterministic backend work and can be reconciled across many
108
+ workspaces; a model does not need to read and approve the same API description
109
+ for every workspace. Persist the returned Integration instance/server IDs and
110
+ skip unchanged desired versions rather than reinstalling on every chat.
111
+
112
+ Create API-key credentials with `createConnection`. Rotate ordinary credentials
113
+ through `updateConnection` with `expectedVersion`; OAuth providers use their
114
+ dedicated reconnect flow. For session-specific MCP headers, later message
115
+ requests may carry the supported MCP credential update. Responses expose
116
+ metadata and credential versions, never the values.
117
+
118
+ OpenGeni encrypts brokered credentials at rest and keeps them out of model
119
+ context. The trusted control plane can decrypt them to call the exact provider;
120
+ the model and sandbox receive only schemas and bounded results. The provider API
121
+ must still enforce tenant/user scope on every operation and must not trust a
122
+ model-supplied tenant ID.
123
+
124
+ ## Runtime Profile And Models
125
+
126
+ Use workspace `agentInstructions` for stable workspace behavior, session
127
+ `instructions` for one role/conversation, Skills for conditional procedures,
128
+ and `modelContext` for current dashboard or route state. Avoid duplicating one
129
+ policy across all four surfaces.
130
+
131
+ Inline Skills are transmitted once in `createSession` and fixed onto that
132
+ session, not sent on each turn. Version the customer-owned runtime profile and
133
+ apply new Skill content to new sessions unless the product deliberately
134
+ migrates old ones.
135
+
136
+ Workspace `sessionDefaults` set the default model and reasoning for new
137
+ sessions. A session or message may override them subject to the workspace model
138
+ access policy. Resolve model IDs from the live client configuration rather than
139
+ hard-coding a remembered list.
140
+
141
+ OpenGeni-credit models in every organization workspace draw from the same
142
+ organization account balance; workspace creation does not create separate
143
+ wallets. Connected subscriptions and workspace-owned provider credentials may
144
+ instead use an externally billed path. Preserve the workspace and product
145
+ boundary in usage attribution when the customer needs a per-user or per-tenant
146
+ view over the shared organization balance.
147
+
148
+ Reconcile stable workspace settings, Connections, Integrations, and runtime
149
+ profile versions during provisioning, startup, deployment, or a controlled
150
+ migration. Do not PATCH the same settings or reinstall the same Integration on
151
+ every chat request when no desired version changed.
152
+
153
+ ## Session Creation Options
154
+
155
+ Beyond `initialMessage`/`tools`/`resources`, the create body (`POST /v1/workspaces/:workspaceId/sessions`, the SDK's `createSession(workspaceId, request)`) chooses where the session runs:
156
+
157
+ - `sandboxBackend` — pick the managed sandbox execution backend; omit for the deployment default.
158
+ - `targetSandboxId` (uuid) — run the session on an enrolled **Connected Machine** (a user-owned machine) instead of a managed sandbox. It seeds the session's active-sandbox pointer at creation so the first turn routes to that machine; an invalid/unowned/offline target fails the create.
159
+ - `workingDir` — the host path the machine runs the session under (the base for its agent cwd, terminal, and file dock). **Only valid together with `targetSandboxId`** — sending `workingDir` alone is a 422. Omit it to use the machine's default working directory.
160
+ - `sandbox` — shared-sandbox placement for managed sandboxes, a three-way union: `"shared"` (join the creating session's box; a top-level `"shared"` is a 422), `"new"` (mint a fresh box), or `{ groupId }` (join a specific sibling group in the same workspace). Omitted resolves a context-dependent default server-side.
161
+ - `idempotencyKey` (1–200 chars) — a workspace-scoped CREATE idempotency key (see below).
162
+
163
+ `targetSandboxId`/`workingDir` are the managed-sandbox-vs-Connected-Machine choice; `sandboxBackend` and the `sandbox` placement union only apply to managed sandboxes. To move a session onto a different machine *after* creation, use the active-sandbox swap (below) — not `updateSession`, whose only field is the session `title`.
164
+
165
+ ## Replay And Retry
166
+
167
+ - Persist the latest event sequence seen by the client.
168
+ - On reconnect, list events after the last known sequence before reopening the stream.
169
+ - Retry idempotent reads and stream reconnects with bounded backoff.
170
+ - Session creation exposes a workspace-scoped `idempotencyKey` (distinct from the per-call `clientEventId`): forward a stable value so concurrent/retried creates of the same logical session collapse to a single session. Without it every create is independent, so a blind retry can double-create — keep sending a stable key when you retry.
171
+ - Treat unknown event types as extensible timeline entries, not client crashes.
172
+
173
+ ## Files
174
+
175
+ The usual flow is:
176
+
177
+ 1. `POST /v1/workspaces/:workspaceId/files/uploads`
178
+ 2. `PUT` bytes to the returned signed object-storage URL with the required headers.
179
+ 3. Complete the upload through the returned workspace upload endpoint.
180
+ 4. Attach the file resource to a session, follow-up turn, or scheduled task only after it is ready.
181
+
182
+ Never attach a file id from another workspace. Correct behavior is no data leak: 403 when the credential has no workspace grant, 404 when the resource is not in the granted workspace.
183
+
184
+ ## Knowledge And Search
185
+
186
+ Uploaded originals remain Files. Attaching a ready file in a normal chat lets the
187
+ accepted agent turn prepare its searchable source content when Knowledge
188
+ authoring is enabled; users do not need a separate document-base upload flow.
189
+ The attempt-bound `knowledge_retain_file` tool provides explicit preparation.
190
+ Retained sources, findings and collections share the canonical Knowledge entries
191
+ API. Use `listKnowledgeEntries` and `getKnowledgeEntry` for retrieval, or the
192
+ first-party `knowledge_*` tools for agents. A finding cites a specific source
193
+ revision; a collection relates existing entries across sources without copying.
194
+
195
+ Default retrieval returns published content. Explicit `view: "needs_review"`
196
+ returns accessible pending proposals as unapproved context, so an agent can
197
+ improve an existing entry instead of creating duplicates. Agent learning resolves
198
+ workspace/personal defaults plus chat or scheduled-task overrides: Automatic
199
+ publishes, Review first stages without pausing work, and Off disables agent
200
+ authoring while retaining authorized retrieval. Conversation history and
201
+ temporary task notes remain separate. Inspect the installed SDK and live schema
202
+ for exact request shapes rather than using the retired Memory writers.
203
+
204
+ ## GitHub Repositories
205
+
206
+ For private repos, use the workspace GitHub repository list before attaching a resource. A valid repository resource normally includes clone URL, ref, mount path, GitHub installation id, and GitHub repository id from OpenGeni's listing response. The worker mints short-lived GitHub App tokens for selected repositories and should not persist clone credentials in session manifests.
207
+
208
+ Do not ask customers to paste GitHub App private keys into their client integration. Managed SaaS uses the OpenGeni-owned app; self-hosted operators configure their own app server-side.
209
+
210
+ ## Connected Machines And Enrollment
211
+
212
+ A Connected Machine is a user-owned machine enrolled into a workspace and used as first-class primary compute (no cloud box behind it; it uses its own git auth; repos are not cloned onto it). `selfhosted` is the internal `sandboxBackend` enum value for such a machine.
213
+
214
+ Discover and target machines:
215
+
216
+ - `GET /v1/workspaces/:workspaceId/machines` — list the workspace's machines (each with its derived state, latest metrics, and shared-session count) plus the active-sandbox pointer. Pass `?sessionId=` for an in-session view that also includes the session's own group box. SDK: `listMachines(workspaceId, { sessionId })`.
217
+ - `GET /v1/workspaces/:workspaceId/machines/:enrollmentId/metrics/series?window=15m|1h|6h|24h` — the downsampled (~1/min) metrics history. SDK: `machineMetricsSeries(workspaceId, enrollmentId, { window })`.
218
+ - Create a session with `targetSandboxId` (a machine's `sandboxId` from the list) plus an optional `workingDir` to run on it.
219
+ - `POST /v1/workspaces/:workspaceId/sessions/:sessionId/active-sandbox` with `{ target }` — swap the session's active sandbox mid-conversation; `target` is a machine's `sandboxId`, or `"session"`/`"default"` to return to the session's own group box. The response echoes `swapped`, `activeSandboxId`, `activeEpoch`, and a `reason` when a target is refused. SDK: `swapActiveSandbox(workspaceId, sessionId, { target })`.
220
+
221
+ Enroll a machine (the client-driven parts):
222
+
223
+ - Interactive device flow: the machine's own agent starts and polls the flow agent-side (unauthenticated). A workspace operator resolves the pending request by user code with `POST /v1/enrollments/device/lookup` (no workspace in the path — the server resolves it from the code, then authorizes `enrollments:read`), then `POST /v1/workspaces/:workspaceId/enrollments/device/approve` (the loud consent step; `allowScreenControl` opts into screen control) or `.../device/deny`. SDK: `lookupDeviceEnrollment(userCode)`, `approveDeviceEnrollment(workspaceId, { userCode, allowScreenControl })`, `denyDeviceEnrollment(workspaceId, { userCode })`.
224
+ - Headless / fleet: `POST /v1/workspaces/:workspaceId/enrollments/token` mints a short-TTL SECRET enroll token (surface it once with a copy-now warning); the machine's agent redeems it agent-side at `POST /v1/enrollments/token/exchange`. SDK: `mintEnrollToken(workspaceId, { allowScreenControl })`.
225
+ - `POST /v1/workspaces/:workspaceId/enrollments/:enrollmentId/revoke` removes a machine. Approving, minting, and revoking all require `enrollments:manage`; listing needs `enrollments:read`.
226
+
227
+ Never distribute an OpenGeni credential to a Connected Machine or try to inject git tokens into it — the machine authenticates to git with its own credentials. Device start/poll and token exchange are agent-side calls, not client SDK methods.
228
+
229
+ ## Billing And Limits
230
+
231
+ Managed SaaS uses prepaid Stripe credits and local usage/cost accounting. Client behavior should be simple:
232
+
233
+ - Show billing/credit status from `/v1/billing` when the user has billing permission.
234
+ - Stop costly writes/runs when the API returns a credit/limit denial.
235
+ - Preserve read/export paths when writes are blocked.
236
+ - Surface top-up links from OpenGeni; do not call Stripe directly from a customer agent unless OpenGeni explicitly returns a Stripe URL.
237
+
238
+ ## Generated Customer Skills
239
+
240
+ When generating a customer-specific agent skill that teaches their coding agents how to call OpenGeni:
241
+
242
+ - Include only their non-secret base URL, organization-workspace mapping
243
+ convention, and safe API examples.
244
+ - Tell the agent to read API keys from the customer's secret manager or environment, never from the skill.
245
+ - State that the backend uses an organization API key, organization workspaces
246
+ have wire `kind: "shared"`, and Personal workspaces are excluded.
247
+ - State where the external product stores Skills and that it passes selected
248
+ definitions inline per session; never invent an organization-wide Skill
249
+ registry or inheritance layer.
250
+ - Keep the skill versioned with their integration code and add a quick smoke command that calls `/v1/config/client` and `/v1/access/me`.
251
+ - State which integration shape the product chose and where its tenant-safe
252
+ proxy/client lives; do not teach every possible shape in every customer skill.
253
+ - Describe only primitives proven by the installed SDK and live deployment; do
254
+ not turn roadmap assumptions into customer instructions.
255
+ - Start from `customer-skill-template.md` in this directory so the generated
256
+ skill records the chosen shape and smoke probes without copying credentials.