opengeni-client

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OpenGeni Client

OpenGeni Client

Use this skill when a customer's product and OpenGeni remain separate systems. That is the normal integration shape: the product owns its users and business UI, while a standalone OpenGeni deployment owns agent sessions and execution.
For first-time organization and workspace provisioning, start with OpenGeni developer setup, then return here to write the embedding code. That skills-only workflow uses the coding agent's own browser and public REST/SDK, with a scoped Developer setup key; no OpenGeni MCP server is required.
Do not confuse two meanings of "skill": this file teaches a customer's coding agent how to integrate OpenGeni; session
skills
are runtime capabilities or instructions attached to an OpenGeni agent. The former designs the integration. The latter is product data sent through the installed SDK contract.
Code and the live service are authoritative. Prefer
/v1/config/client
,
/v1/access/me
, the installed package types, and live probes over memorized route, model, tool, or backend lists. When source is available, verify exact behavior in
packages/sdk
,
packages/react
, contracts, and API routes. Read
docs/product-integration.md
when the repository is available; it is the canonical product boundary for organization keys, workspace mapping, and Skill ownership.
Without repository access, start at https://docs.opengeni.ai/llms.txt and fetch the relevant Markdown pages. Before replacing an AI provider, answering a cost question, or reporting a setup blocker, read Compatibility and troubleshooting.
当客户的产品与 OpenGeni 保持为独立系统时,使用此 skill。这才是常规的集成形态:产品负责自身用户和业务 UI,而独立的 OpenGeni deployment 负责 agent session 和执行。
首次配置 organization 和 workspace 时,先阅读 OpenGeni developer setup,然后返回本文编写嵌入代码。该仅限 Skills 的工作流使用编程 Agent 自身的浏览器以及公共 REST/SDK,并配以权限受限的 Developer setup key;无需 OpenGeni MCP server。
不要混淆 "skill" 的两种含义:本文教授客户的编程 Agent 如何集成 OpenGeni;session 的
skills
则是附加到某个 OpenGeni Agent 的运行时能力或指令。前者用于设计集成,后者是通过已安装 SDK 契约发送的产品数据。
代码和线上服务才是权威依据。相较于凭记忆列出 route、model、tool 或 backend,应优先使用
/v1/config/client
、
/v1/access/me
、已安装 package 类型及实时探测。若可访问源码,应在
packages/sdk
、
packages/react
、contracts 和 API routes 中核实确切行为。仓库可用时,务必阅读
docs/product-integration.md
;它是界定 organization key、workspace 映射和 Skill 归属的权威产品边界。
无法访问仓库时,先访问 https://docs.opengeni.ai/llms.txt 并获取相关 Markdown 页面。在替换 AI provider、回答成本问题或报告 setup blocker 之前,务必阅读 Compatibility and troubleshooting。

Work Adaptively

灵活应变

This same guide is bundled as
builtin:opengeni-client
in ordinary OpenGeni sessions and lives in
.agents/skills/opengeni-client
for external coding agents. No Pack, installation, repository clone, or sandbox is needed to read the bundled copy. It is guidance, not authority to access a repository, secret, or deployment. Embedded products may narrow bundled guidance with
bundledSkillIds
.
  • Inspect before you build. In the customer's repository: authentication, tenancy, data routes, frontend conventions, installed packages, tests, CI, deployment guidance, and any OpenGeni code already there. In OpenGeni:
    getClientConfig()
    (is
    agentConfig.enabled
    ? which capabilities are offered?), the workspace's
    settings.sessionAgentDefaults
    , and an existing session's
    agent
    and
    effectiveTools
    . Only then ask questions or choose an integration shape.
  • If the target repository or resources are missing, first inspect available authorized resources and connection/setup tools. Help the user connect or attach the specific missing source; explain the next action in product terms. Continue useful discovery without requesting broad credentials or pretending missing access is configured. Read Discovery and autonomy for that workflow.
  • Two choices belong to the user: who can see a chat (only the person who started it, or their team) and whether the agent may change data. If the request or repository does not settle one, ask ONE short, plain-language question with a recommended answer, before building. Never ask what the repository answers. How chats map to OpenGeni workspaces (including
    chats: "isolated"
    ) is your implementation decision: never offer it as an option or mention OpenGeni workspaces in a question.
  • Decide local-development mechanics yourself (ports, local HTTPS, cookie flags, seed data, test logins). When you test against a local app, OpenGeni must reach its tool endpoint over public HTTPS, so open a temporary tunnel (for example
    cloudflared
    ) and tell the user you did; don't ask.
  • Do not ask about background work, schedules, session length or credential lifetime up front. Long agent sessions just work. Only when the requested feature itself is scheduled or runs in the background (for example "email me a weekly report"), ask for the missing details (day, time, time zone, where results appear) and say in one sentence why you need them. See Discovery and autonomy.
  • Use a reversible, clearly stated default only for choices outside those four, or when the user explicitly said not to ask. A busy user is not that signal.
  • Match the requested delivery autonomy. Repository or cloud access is technical capability, not permission to push, deploy, merge, or change production.
  • This Skill guides an implementation agent. Never copy it into the runtime Skills of the customer-facing agent.
本指南既会作为
builtin:opengeni-client
打包进普通 OpenGeni session,也会位于外部编程 Agent 的
.agents/skills/opengeni-client
。读取内置副本无需 Pack、安装、克隆仓库或使用 sandbox。它只是指导,并不授予访问仓库、secret 或 deployment 的权限。嵌入式产品可通过
bundledSkillIds
收窄内置指导范围。
  • 构建前先检查。在客户仓库中检查:认证、租户、数据路由、前端约定、已安装 package、测试、CI、部署指南以及已有的 OpenGeni 代码。在 OpenGeni 中检查:
    getClientConfig()
    (是否启用了
    agentConfig.enabled
    ?提供了哪些 capabilities?)、workspace 的
    settings.sessionAgentDefaults
    ,以及现有 session 的
    agent
    和
    effectiveTools
    。完成这些检查后,再提出问题或选择集成形态。
  • 如果目标仓库或资源缺失,先检查可用的授权资源和连接或配置工具。帮助用户连接或附加具体缺失来源;以产品术语说明下一步操作。在不索要宽泛凭据、也不假装缺失访问已配置的情况下,继续开展有价值的发现。阅读 Discovery and autonomy 以了解该工作流。
  • 有两个选择属于用户:谁能看到某个 chat(仅发起者,还是其团队),以及 Agent 是否可以更改数据。如果请求或仓库无法确定,应在构建前提出一个简短、平实的问题,并给出推荐答案。绝不要询问仓库本身已能回答的问题。如何将 chat 映射到 OpenGeni workspace,包括
    chats: "isolated"
    ,属于实现决策:绝不能把它作为选项提出,也不要在问题中提及 OpenGeni workspace。
  • 自行决定本地开发机制,包括端口、本地 HTTPS、cookie 标志、种子数据和测试登录。针对本地应用进行测试时,OpenGeni 必须通过公共 HTTPS 访问其工具端点,因此应开启临时隧道(例如
    cloudflared
    )并告知用户;不要询问。
  • 不要预先询问后台任务、计划、会话时长或凭据有效期。长时间 agent session 可以直接运行。只有当所请求的功能本身需要计划执行或在后台运行时,例如“每周给我发送一份报告”,才询问缺失信息,包括日期、时间、时区和结果显示位置,并用一句话说明为何需要这些信息。参阅 Discovery and autonomy。
  • 仅对上述四项之外的选择,或用户明确表示无需询问时,才采用可逆且明确说明的默认值。单纯说用户很忙并不构成这一信号。
  • 匹配请求所要求的交付自主权。拥有仓库或云访问权限是技术能力,并不等于获准 push、deploy、merge 或更改 production。
  • 此 Skill 用于指导 implementation agent。绝不能将其复制到面向客户的 Agent 的运行时 Skills 中。

Default: the full conversation behind a packaged proxy

默认方案:通过打包代理提供完整对话

Default to OpenGeni's complete conversation experience:
OpenGeniProvider
,
OpenGeniChat
(the user's chat list plus
SessionConversation
) from
@opengeni/react/session-ui
, and
@opengeni/react/compiled.css
. For custom-branded embeds, theme with scoped
--og-*
tokens. For stock UI, use the shipped components and stylesheet without cosmetic host CSS or token overrides; see Stock and host-branded appearance. Import from
session-ui
, not the package root: the root also exports the workbench, whose editors, terminal and desktop viewer are optional peer dependencies your bundler would try to resolve. The UI is backed by the normal session SDK through
createSessionProxyHandler
, a tenant/user-scoped same-origin proxy on the product server with Next.js, Express, and Hono adapters (other backends: see Proxy from any backend). It already provides streaming, replay, queue, steer, approvals, human input, attachments, and pause/resume. Deviate only when the product needs a materially different interaction model, a non-React frontend, or compute surfaces, and record why.
ts
// Server only: the organization API key never reaches the browser.
import { OpenGeniClient } from "@opengeni/sdk";
import { createSessionProxyRoute } from "@opengeni/sdk/next";

const og = new OpenGeniClient({
  baseUrl: process.env.OPENGENI_API_BASE_URL!, // the deployment you target
  apiKey: process.env.OPENGENI_API_KEY!, // organization API key
});
const source = "acme-app"; // stable external-identity namespace

// 1. Onboarding, once per tenant and admitted user (persist workspace.id and operationId).
const { workspace } = await og.ensureWorkspace({
  accountId: process.env.OPENGENI_ORGANIZATION_ID!, externalSource: source,
  externalId: tenant.id, name: tenant.name,
});
await og.addExternalWorkspaceMember(workspace.id, {
  identity: { externalId: user.id, source },
  permissions: ["workspace:read", "sessions:create", "sessions:read", "sessions:control",
    "files:upload", "files:read", "mcp_servers:attach"], // attach: per-session mcpServers
  operationId,
});

// 2. The proxy, as a Next.js App Router catch-all: app/api/opengeni/[...path]/route.ts.
//    Express: toNodeMiddleware(createSessionProxyHandler(og, options)) from
//    "@opengeni/sdk/express"; Hono: toHonoHandler(...) from "@opengeni/sdk/hono".
const acme = (token: string) => ({ id: "acme", headers: { Authorization: `Bearer ${token}` } });
export const dynamic = "force-dynamic";
export const { GET, POST, PUT, PATCH, DELETE } = createSessionProxyRoute(og, {
  chats: "private", // the default: each user's chats are theirs; "shared" | "isolated"
  resolve: async (request) => {
    const me = await authenticate(request); // the product's own session check
    return me
      ? { workspaceId: me.openGeniWorkspaceId, user: me.id, source }
      : new Response("Unauthorized", { status: 401 });
  },
  authorizeMutation: verifyCsrf, // the product's existing CSRF policy
  // New chats: the browser sends only the first message; the server picks the rest.
  createSession: async ({ initialMessage, idempotencyKey }, { user }) => ({
    initialMessage,
    idempotencyKey,
    agent: {
      identity: "You are Acme's support assistant. Friendly and brief.",
      capabilities: "none", // Acme's tools, asking questions, reading Skills; nothing else
    },
    skills: productSkills, // product-owned, inline
    mcpServers: [{ ...acme(await mintUserToken(user)), url: ACME_MCP_URL, allowedTools }],
    tools: [{ kind: "mcp", id: "acme" }], // a per-session server must also be selected here
    sandboxBackend: "none", // pure chat/tool agent: no sandbox to start or shell around tools
  }),
  // Every forwarded message: fresh per-user token and server-owned page context.
  beforeForwardMessage: async (_message, { user }) => ({
    mcpCredentialUpdates: [acme(await mintUserToken(user))],
    modelContext: `Today ${new Date().toISOString().slice(0, 10)}, time zone ${tz}`,
  }),
});
tsx
// Browser: the unmodified SDK client, pointed at the mount.
import { OpenGeniClient } from "@opengeni/sdk";
import { OpenGeniChat, OpenGeniProvider } from "@opengeni/react/session-ui";
import "@opengeni/react/compiled.css";

const client = new OpenGeniClient({ baseUrl: "/api/opengeni" });
<OpenGeniProvider client={client} workspaceId={workspaceId}>
  <OpenGeniChat /> {/* the user's chats (sidebar/drawer) + conversation */}
</OpenGeniProvider>;
agent
needs the deployment's agent settings (
agentConfig.enabled
in the client config); on an older or rollout-disabled deployment send
firstPartyMcpTools: []
instead of
agent
and see Configure the agent.
For an assistant bound to one record (a ticket, a dashboard), create the session server-side as the user (
og.asUser(user.id, { source }).createSession(...)
with a stable
idempotencyKey
) and render
<SessionConversation sessionId>
. The proxy calls
resolve
per request, acts only through
asUser
, pins the workspace, and serves only provider/conversation routes; the chat list shows only chats the user created (
sessionList: "visible"
widens it). Never replace the proxy with a raw passthrough of arbitrary paths under the organization key. Reset UI state when the user or tenant changes.
默认采用 OpenGeni 的完整对话体验:
OpenGeniProvider
、
OpenGeniChat
(用户的 chat 列表以及
SessionConversation
),二者来自
@opengeni/react/session-ui
,并使用
@opengeni/react/compiled.css
。对于自定义品牌的嵌入,使用限定作用域的
--og-*
token 进行主题化。对于原生 UI,直接使用随附的组件和样式表,不添加外观层面的宿主 CSS 或 token 覆盖;参阅 Stock and host-branded appearance。
从
session-ui
导入,不要从 package 根路径导入:根路径还会导出 workbench,其 editors、terminal 和 desktop viewer 是可选 peer dependency,而 bundler 会尝试解析它们。该 UI 通过
createSessionProxyHandler
连接到普通 session SDK;这是一个运行在产品服务端、按 tenant 和 user 限定范围的同源 proxy,提供 Next.js、Express 和 Hono adapter(其他后端参阅 Proxy from any backend)。它已经支持 streaming、replay、queue、steer、approvals、human input、attachments 以及 pause/resume。只有当产品需要实质上不同的交互模型、非 React 前端或 compute surfaces 时才应偏离默认方案,并记录原因。
ts
// Server only: the organization API key never reaches the browser.
import { OpenGeniClient } from "@opengeni/sdk";
import { createSessionProxyRoute } from "@opengeni/sdk/next";

const og = new OpenGeniClient({
  baseUrl: process.env.OPENGENI_API_BASE_URL!, // the deployment you target
  apiKey: process.env.OPENGENI_API_KEY!, // organization API key
});
const source = "acme-app"; // stable external-identity namespace

// 1. Onboarding, once per tenant and admitted user (persist workspace.id and operationId).
const { workspace } = await og.ensureWorkspace({
  accountId: process.env.OPENGENI_ORGANIZATION_ID!, externalSource: source,
  externalId: tenant.id, name: tenant.name,
});
await og.addExternalWorkspaceMember(workspace.id, {
  identity: { externalId: user.id, source },
  permissions: ["workspace:read", "sessions:create", "sessions:read", "sessions:control",
    "files:upload", "files:read", "mcp_servers:attach"], // attach: per-session mcpServers
  operationId,
});

// 2. The proxy, as a Next.js App Router catch-all: app/api/opengeni/[...path]/route.ts.
//    Express: toNodeMiddleware(createSessionProxyHandler(og, options)) from
//    "@opengeni/sdk/express"; Hono: toHonoHandler(...) from "@opengeni/sdk/hono".
const acme = (token: string) => ({ id: "acme", headers: { Authorization: `Bearer ${token}` } });
export const dynamic = "force-dynamic";
export const { GET, POST, PUT, PATCH, DELETE } = createSessionProxyRoute(og, {
  chats: "private", // the default: each user's chats are theirs; "shared" | "isolated"
  resolve: async (request) => {
    const me = await authenticate(request); // the product's own session check
    return me
      ? { workspaceId: me.openGeniWorkspaceId, user: me.id, source }
      : new Response("Unauthorized", { status: 401 });
  },
  authorizeMutation: verifyCsrf, // the product's existing CSRF policy
  // New chats: the browser sends only the first message; the server picks the rest.
  createSession: async ({ initialMessage, idempotencyKey }, { user }) => ({
    initialMessage,
    idempotencyKey,
    agent: {
      identity: "You are Acme's support assistant. Friendly and brief.",
      capabilities: "none", // Acme's tools, asking questions, reading Skills; nothing else
    },
    skills: productSkills, // product-owned, inline
    mcpServers: [{ ...acme(await mintUserToken(user)), url: ACME_MCP_URL, allowedTools }],
    tools: [{ kind: "mcp", id: "acme" }], // a per-session server must also be selected here
    sandboxBackend: "none", // pure chat/tool agent: no sandbox to start or shell around tools
  }),
  // Every forwarded message: fresh per-user token and server-owned page context.
  beforeForwardMessage: async (_message, { user }) => ({
    mcpCredentialUpdates: [acme(await mintUserToken(user))],
    modelContext: `Today ${new Date().toISOString().slice(0, 10)}, time zone ${tz}`,
  }),
});
tsx
// Browser: the unmodified SDK client, pointed at the mount.
import { OpenGeniClient } from "@opengeni/sdk";
import { OpenGeniChat, OpenGeniProvider } from "@opengeni/react/session-ui";
import "@opengeni/react/compiled.css";

const client = new OpenGeniClient({ baseUrl: "/api/opengeni" });
<OpenGeniProvider client={client} workspaceId={workspaceId}>
  <OpenGeniChat /> {/* the user's chats (sidebar/drawer) + conversation */}
</OpenGeniProvider>;
agent
需要使用 deployment 的 agent 设置,即 client config 中的
agentConfig.enabled
;如果 deployment 版本较旧或 rollout 尚未启用,则改为发送
firstPartyMcpTools: []
,并参阅 Configure the agent。
对于绑定到单条记录(例如 ticket 或 dashboard)的 Assistant,应在服务端以用户身份创建 session,使用
og.asUser(user.id, { source }).createSession(...)
并提供稳定的
idempotencyKey
,然后渲染
<SessionConversation sessionId>
。Proxy 会在每次请求时调用
resolve
,只通过
asUser
执行操作,固定 workspace,并且只提供 provider 和 conversation routes;chat 列表仅显示用户创建的 chats,使用
sessionList: "visible"
可扩大范围。绝不能用 organization key 下任意路径的原始直通来替换 proxy。用户或 tenant 发生变化时,重置 UI 状态。

Migrating from embedded OpenGeni

从嵌入式 OpenGeni 迁移

When moving old in-process sessions to a standalone deployment, read Archived session history import. Use server-only functions from
@opengeni/sdk/session-history-import
, with the existing tenant mappings and verified
asUser
creator/owner. Preserve timestamps and visibility, re-upload files and replace references before import, and retain exact import/batch requests for idempotent retries. This is a read-only event archive, never model-facing history or resumable execution. Keep
SessionConversation
behind the existing proxy; imported archives never offer Send or Steer, and continuation is unsupported in v1. Do not add import routes to the browser proxy or attach this implementation Skill to end-user agents.
将旧的进程内 sessions 迁移到独立 deployment 时,阅读 Archived session history import。使用从
@opengeni/sdk/session-history-import
导入的仅限服务端函数,并沿用现有的 tenant mappings 以及经过验证的
asUser
creator/owner。保留时间戳和可见性,在导入前重新上传文件并替换引用,同时保留完全相同的 import/batch requests,以便进行幂等重试。这是一种只读 event archive,绝不能作为面向模型的历史记录或可恢复的执行环境。保持
SessionConversation
位于现有 proxy 之后;导入的 archives 永远不提供 Send 或 Steer,且 v1 不支持继续执行。不要向浏览器 proxy 添加 import routes,也不要将此 implementation Skill 附加到面向最终用户的 Agent。

Deliberate deviations

有意采用的偏离方案

Choose one only for its stated reason; read Product shapes and UI first.
  • Headless React hooks (
    @opengeni/react/session
    ): the product needs a materially different interaction model but still wants canonical event, queue, composer, approval, and human-input behavior.
  • SDK only: a non-React frontend (Svelte, Vue, native mobile), a CLI, or backend automation. Keep the SDK on a product backend route. For a runnable native Vue host, start with the Vue conversation recipe. Run its consumer commands from
    examples/vue-conversation/app
    .
  • A non-JavaScript backend (Django, Rails, Go, PHP, Java): keep the React conversation and implement the proxy's small HTTP contract in that backend instead of adding a Node sidecar. See Proxy from any backend.
  • Workbench: the product genuinely exposes agent compute (changes, files, terminal, desktop). It has optional heavy peers.
  • Chat facade fallback (
    @opengeni/sdk/chat
    ): the product already has a chat UI speaking Vercel
    useChat
    or an OpenAI-shaped protocol, or a server-side bot needs
    og.chat(...).send()
    . It is a text-only projection: tool outputs are dropped, with no files, artifacts, images, goals, queue, or steer UI, and reopening restores only text. See Chat facade fallback.
  • In-process embedding of the OpenGeni runtime is infrastructure work; see the repo-maintainer
    opengeni
    skill and
    docs/embedding.md
    .
Verify delivery with representative product questions, checking useful answers and actual tool execution, not just connectivity: see Integration configuration and verification. Read selectively: Product integration shapes, API workflows, Isolation and authorization, Data tools and credentials, and External users and embedded connection setup.
仅基于明确理由选择其中一种;先阅读 Product shapes and UI。
  • Headless React hooks(
    @opengeni/react/session
    ):产品需要实质上不同的交互模型,但仍希望使用标准的事件、队列、输入框、审批和人工输入行为。
  • 仅使用 SDK:使用非 React 前端,例如 Svelte、Vue 或原生移动端,或者用于 CLI 和后端自动化。将 SDK 放在产品后端 route 上。对于可运行的原生 Vue host,请从 Vue conversation recipe 开始。从
    examples/vue-conversation/app
    运行其 consumer commands。
  • 非 JavaScript 后端,例如 Django、Rails、Go、PHP 或 Java:保留 React conversation,并在该后端中实现 proxy 的小型 HTTP contract,而不是增加 Node sidecar。参阅 Proxy from any backend。
  • Workbench:产品确实需要公开 Agent compute,包括更改、文件、terminal 和 desktop。它包含可选的重型 peer dependencies。
  • Chat facade fallback(
    @opengeni/sdk/chat
    ):产品已有使用 Vercel
    useChat
    或 OpenAI 风格协议的 chat UI,或者服务端 bot 需要使用
    og.chat(...).send()
    。它仅是纯文本投影:会丢弃 tool outputs,不支持 files、artifacts、images、goals、queue 或 steer UI,重新打开时也只恢复文本。参阅 Chat facade fallback。
  • OpenGeni runtime 的进程内嵌入属于基础设施工作;参阅 repo maintainer 的
    opengeni
    skill 和
    docs/embedding.md
    。
通过有代表性的产品问题验证交付情况,检查有用的答案和实际工具执行情况,而不只是验证连通性:参阅 Integration configuration and verification。选择性阅读:Product integration shapes、API workflows、Isolation and authorization、Data tools and credentials 和 External users and embedded connection setup。

Configure The Agent

配置 Agent

Every surface takes one
agent
object:
capabilities
(start from
"all"
or
"none"
, then switch
webSearch
,
humanInput
,
skills
,
goals
,
subagents
,
knowledge
,
schedules
,
artifacts
,
browser
,
media
,
workspaceFiles
,
workspaceConnectors
,
workspaceAdmin
),
identity
(who the agent is),
instructions
and
renderer
(
"opengeni"
for OpenGeni's React components,
"markdown"
for your own UI). Pick capabilities from the product's intent, not from tool names: a customer-facing assistant usually starts from
"none"
plus what it needs; an internal operator agent from
"all"
minus what it must not do. Set workspace defaults with
sessionAgentDefaults
, schedules with
agentConfig.agent
, and change a running session with
updateSessionAgent
(from its next turn). Check the result on
session.agent
and
session.effectiveTools
. Read Configure the agent before choosing; it also covers
chats
, the admission switch and error codes.
For per-seat included usage, administrator splits, top-ups, team budgets, or browser progress meters, read Usage allowances. Keep organization-budget writes on the backend; the conversation proxy exposes only own usage. These are post-call ceilings, not prepaid reservations.
每种 surface 都接收一个
agent
对象:
capabilities
(从
"all"
或
"none"
开始,然后按需切换
webSearch
、
humanInput
、
skills
、
goals
、
subagents
、
knowledge
、
schedules
、
artifacts
、
browser
、
media
、
workspaceFiles
、
workspaceConnectors
、
workspaceAdmin
)、
identity
(Agent 是谁)、
instructions
以及
renderer
(
"opengeni"
表示使用 OpenGeni 的 React components,
"markdown"
表示使用自己的 UI)。应根据产品意图而不是 tool 名称来选择 capabilities:面向客户的 Assistant 通常从
"none"
开始,再添加所需能力;内部 operator Agent 则从
"all"
开始,再移除不允许的能力。使用
sessionAgentDefaults
设置 workspace 默认值,使用
agentConfig.agent
设置 schedules,并通过
updateSessionAgent
更改正在运行的 session,改动从其下一轮开始生效。检查
session.agent
和
session.effectiveTools
中的结果。选择之前请阅读 Configure the agent;该文档还涵盖
chats
、准入开关和错误码。
对于按席位计算包含用量、管理员分摊、充值、团队预算或浏览器进度计量,阅读 Usage allowances。organization budget 的写入操作必须保留在后端;conversation proxy 仅公开用户自己的用量。这些限制是调用后的上限,而不是预付预留。

Build Gotchas

构建时的常见问题

  • Always pass
    baseUrl
    (
    process.env.OPENGENI_API_BASE_URL
    ); the chat facade otherwise targets production
    app.opengeni.ai
    . The SDK is ESM-only.
  • A per-session
    mcpServers
    entry is usable only when also selected in
    tools: [{ kind: "mcp", id, eager? }]
    , and attaching it needs
    mcp_servers:attach
    for the acting user. MCP and OpenAPI spec URLs must be public HTTPS the deployment can reach; tunnel local servers (for example
    cloudflared
    ).
  • Install
    @opengeni/sdk
    and
    @opengeni/react
    from the same release. If the repository enforces a release-age policy (for example pnpm
    minimumReleaseAge
    ), a just-published version may be refused: pin an older matching pair or ask before adding an exclusion; never bypass it silently.
  • External member permissions cannot yet be edited in place (a re-grant with a new
    operationId
    conflicts, and the organization key cannot update the member). Grant the final set at onboarding; to change it, revoke (
    cancelExternalWorkspaceMemberGrant
    , which cancels that user's running turns) and re-add with a new
    operationId
    .
  • sandboxBackend: "none"
    suits pure chat/tool agents: turns start in seconds instead of minutes, and there is no shell to route around the product's tools.
  • For the smallest agent and prompt, see Agent recipes.
  • Stop in a chat UI is
    pauseSession
    : resumable, and messages sent while paused queue until
    resumeSession
    .
    cancelSession
    is terminal for the session and its children; never wire it to Stop.
  • Background agents: use a scheduled task (
    createScheduledTask
    , with an explicit schedule and time zone), or an inbound automation webhook for events. Their agents reference a workspace OpenAPI Integration or MCP connection by id in
    tools
    (scheduled tasks take no inline
    mcpServers
    ) and write results back through the product's own tools. On deployments with workspace integrations (check
    /v1/config/client
    and the SDK exports), a signed workspace webhook (
    createWorkspaceWebhook
    , verify with
    verifyWebhookEvent
    ) tells the product when turns finish or need a person; treat it as an at-least-once, unordered signal and read the session (see
    docs/workspace-integrations.md
    ).
  • Advanced, not the default path: products that need background work with host-owned access can add a workspace credential provider (short-lived sandbox credentials, including Git) and recognize the calling turn from the informational
    _meta.opengeni
    on MCP calls. See
    docs/workspace-integrations.md
    .
  • Organization integration administration, webhook reads and signing-secret rotation use functions imported from
    @opengeni/sdk/workspace-integrations
    , with
    client
    as the first argument. They are not eager client methods; see Data tools and credentials.
  • 始终传入
    baseUrl
    (
    process.env.OPENGENI_API_BASE_URL
    );否则 chat facade 会指向生产环境
    app.opengeni.ai
    。SDK 仅支持 ESM。
  • 每 session 的
    mcpServers
    条目只有在
    tools: [{ kind: "mcp", id, eager? }]
    中同时被选中后才可使用;附加它还需要 acting user 拥有
    mcp_servers:attach
    。MCP 和 OpenAPI spec URL 必须是 deployment 可访问的公共 HTTPS;请为本地 server 建立隧道,例如
    cloudflared
    。
  • 从同一 release 安装
    @opengeni/sdk
    和
    @opengeni/react
    。如果仓库要求遵守 release-age policy,例如 pnpm
    minimumReleaseAge
    ,刚发布的版本可能会被拒绝:固定到较旧且彼此匹配的版本对,或在添加 exclusion 前先询问;绝不能静默绕过。
  • 外部成员权限目前无法原地修改。使用新的
    operationId
    重新授权会产生冲突,而且 organization key 无法更新成员。在 onboarding 时授予最终权限集;如需更改,先撤销(
    cancelExternalWorkspaceMemberGrant
    ,这会取消该用户正在运行的 turns),再使用新的
    operationId
    重新添加。
  • sandboxBackend: "none"
    适合纯 chat/tool Agent:turn 会在数秒而非数分钟内启动,并且不存在可绕开产品 tools 的 shell。
  • 如需最小的 Agent 和 prompt,请参阅 Agent recipes。
  • Chat UI 中的 Stop 是
    pauseSession
    :可以恢复,且暂停期间发送的消息会排队,直至
    resumeSession
    。
    cancelSession
    是 session 及其子项的终止操作;绝不能将其连接到 Stop。
  • 后台 Agent:使用 scheduled task(
    createScheduledTask
    ,明确指定 schedule 和 time zone),或使用面向事件的入站 automation webhook。它们的 Agent 通过 id 引用 workspace OpenAPI Integration 或 MCP connection,并将其放入
    tools
    (scheduled task 不接受内联
    mcpServers
    ),再通过产品自己的 tools 写回结果。在支持 workspace integrations 的 deployment 上,检查
    /v1/config/client
    和 SDK exports;已签名的 workspace webhook(
    createWorkspaceWebhook
    ,使用
    verifyWebhookEvent
    验证)可在 turn 完成或需要人工处理时通知产品。将其视为至少一次投递且无序的信号,并读取 session;参阅
    docs/workspace-integrations.md
    。
  • 这是一条高级且非默认路径:需要使用 host-owned access 执行后台工作的产品,可以添加 workspace credential provider,包括短期 sandbox credentials 和 Git,并通过 MCP calls 上 informational 的
    _meta.opengeni
    识别调用方 turn。参阅
    docs/workspace-integrations.md
    。
  • Organization integration 管理、webhook 读取和 signing-secret 轮换使用从
    @opengeni/sdk/workspace-integrations
    导入的函数,并以
    client
    作为第一个参数。它们不是 eager client methods;参阅 Data tools and credentials。

Choose The Credential

选择凭据

  • Use an organization API key when one server-side product integration provisions or manages many organization workspaces in one OpenGeni organization.
  • Use a workspace API key when the integration is deliberately constrained to one organization workspace and should not provision others.
  • Use a delegated token when the host acts with short-lived, explicit user/workspace authority rather than one standing product credential.
  • A deployment access key is a coarse deployment perimeter. Never use it as tenant identity or infer organization/workspace authority from it.
  • 当一个服务端产品集成需要在同一个 OpenGeni organization 中配置或管理许多 organization workspaces 时,使用 organization API key。
  • 当集成被明确限制在一个 organization workspace,且不应配置其他 workspace 时,使用 workspace API key。
  • 当 host 以短期且明确授予的 user/workspace authority 行事,而不是依赖一个长期有效的产品凭据时,使用 delegated token。
  • Deployment access key 是粗粒度的 deployment 边界。绝不能将其用作 tenant identity,也绝不能从中推断 organization/workspace authority。

Default Trust Boundary

默认信任边界

  • Keep the organization API key and operator credentials on the product server.
  • Authenticate the product's user first, resolve their allowed OpenGeni workspace/session server-side, and expose only the routes that product needs.
  • Use
    createSessionProxyHandler
    for the React conversation, or
    proxySessionEventStream
    inside a custom same-origin SSE route.
  • Direct browser access is valid only when the deployment's normal browser auth or an explicitly accepted bearer/CORS design makes it safe. Never ship a privileged shared API key in a browser bundle.
The product owns external identity, tenant-to-workspace mapping, business entities, navigation, presentation, and product-specific admission. OpenGeni owns sessions, turns, durable event history, approvals, agent execution, selected tools/resources, files, realtime session state, and compute lifecycle. Link records by opaque IDs; do not copy one system's whole data model into the other.
  • 将 organization API key 和 operator credentials 保留在产品服务端。
  • 首先认证产品用户,在服务端解析其获准访问的 OpenGeni workspace/session,并且只暴露产品需要的 routes。
  • React conversation 使用
    createSessionProxyHandler
    ,或在自定义同源 SSE route 内使用
    proxySessionEventStream
    。
  • 只有当 deployment 的常规 browser auth,或明确接受且安全的 bearer/CORS 设计能够保障安全时,才允许浏览器直接访问。绝不能把特权 shared API key 放入 browser bundle。
产品负责 external identity、tenant-to-workspace mapping、business entities、navigation、presentation 和 product-specific admission。OpenGeni 负责 sessions、turns、durable event history、approvals、agent execution、所选 tools/resources、files、realtime session state 和 compute lifecycle。通过 opaque IDs 关联记录;不要将一个系统的完整数据 model 复制到另一个系统。

Organization And Workspace Bootstrap

Organization 和 Workspace Bootstrap

Use one organization API key for the external backend (
createOrganizationApiKey
,
listOrganizationApiKeys
,
deleteOrganizationApiKey
); the token is shown once, so store it in the product's secret manager.
A full-access organization API key is all the integration needs. It creates workspaces (
ensureWorkspace
,
workspaceIdFor
), adds external members, and creates and controls sessions as those users (
asUser
). Do not judge it by
/v1/access/me
's
accountGrants
(
account:read
,
workspace:create
,
api_keys:manage
) or its empty
workspaceGrants
: those list account-level grants, not what the key may do inside shared workspaces. Check
credential.access === "full"
and
credential.effectiveWorkspacePermissions
instead; older deployments omit
credential
, so if it is missing, try the call (
ensureWorkspace
is idempotent) rather than concluding the key is too weak. Only an
access: "read"
key is limited, to reading.
For each chosen product sharing boundary, call
ensureWorkspace
/
PUT /v1/workspaces/external
with a stable external mapping identity and persist the returned
result.workspace.id
;
result.created
distinguishes the first insert from an idempotent replay. Call it an organization workspace in customer guidance; its exact wire kind is
"shared"
. Personal workspaces are excluded and must never be selected through a default-workspace fallback.
Choose the workspace from who shares documents, workspace instructions, Connections, and integrations: normally one per customer, and a separate one when groups need different Connections, integrations, or instructions. When each end user is their own boundary, a workspace per user (the user id as
externalId
) called with the organization key alone is a valid, simpler option;
chats: "isolated"
provisions exactly that per tenant user. Otherwise use
asUser(externalId)
for the authenticated product user; the server derives the canonical user, so never supply an
endUser
label as authority.
Choose chat privacy with
chats
on the proxy or facade:
"private"
(the default: only the user sees their chats, the agent reaches only its own session, Knowledge goes to the user's personal Knowledge),
"shared"
(the workspace sees and shares them), or
"isolated"
(private, in a workspace per tenant user). Private chats need the organization's private-session setting; without it the SDK throws
OpenGeniSetupError
naming who can enable it.
chats
sets
visibility
,
agentAccess
and
memoryScope
, which stay available as explicit create fields; private sessions do not make workspace Files or Sites private, and removing tools is not a substitute for private visibility. Unscoped organization-key-created top-level sessions are workspace-visible. See
references/external-users-and-connect.md
.
The external backend owns product Skills. Store and version them outside OpenGeni, then pass the selected definitions inline in
CreateSessionRequest.skills
for each product-created session. There is no organization-wide Skill registry or Skill inheritance in this integration contract.
CreateSessionRequest.bundledSkillIds
narrows OpenGeni's bundled guidance (omitted = defaults,
[]
= none); children, scheduled tasks, and automations accept it too. It grants no tools and does not hide workspace or inline Skills.
New Skill inputs require valid
SKILL.md
frontmatter, which owns the name and description. Do not replay old headerless Skills as new session input.
对外部 backend 使用一个 organization API key(
createOrganizationApiKey
、
listOrganizationApiKeys
、
deleteOrganizationApiKey
);token 只显示一次,因此应将其存储在产品的 secret manager 中。
一个全访问 organization API key 就足以满足集成需要。 它可以创建 workspaces(
ensureWorkspace
、
workspaceIdFor
)、添加 external members,以及以这些用户的身份创建和控制 sessions(
asUser
)。不要根据
/v1/access/me
中的
accountGrants
(
account:read
、
workspace:create
、
api_keys:manage
)或空的
workspaceGrants
来判断其能力;这些字段列出的是 account-level grants,而不是 key 在 shared workspaces 内可以执行的操作。检查
credential.access === "full"
和
credential.effectiveWorkspacePermissions
;较旧的 deployment 不会返回
credential
,因此如果缺少该字段,应尝试调用(
ensureWorkspace
是幂等的),而不是直接判断 key 权限不足。只有
access: "read"
的 key 被限制为只读。
对于每个选定的产品共享边界,使用稳定的 external mapping identity 调用
ensureWorkspace
或
PUT /v1/workspaces/external
,并持久化返回的
result.workspace.id
;
result.created
可用于区分首次插入和幂等重放。在面向客户的指导中称其为 organization workspace;其准确的 wire kind 是
"shared"
。Personal workspaces 不在此范围内,绝不能通过 default-workspace fallback 选中。
根据谁共享 documents、workspace instructions、Connections 和 integrations 来选择 workspace:通常每个 customer 使用一个;当 groups 需要不同的 Connections、integrations 或 instructions 时,应单独创建一个。当每个 end user 自身就是边界时,可以为每个用户创建一个 workspace,以 user id 作为
externalId
,仅使用 organization key 调用也是有效且更简单的选项;
chats: "isolated"
正是按 tenant user 配置这一方式。否则,使用
asUser(externalId)
表示已认证的产品用户;server 会派生 canonical user,因此绝不能将
endUser
标签作为 authority 提供。
通过 proxy 或 facade 上的
chats
选择 chat privacy:
"private"
(默认:只有用户能看到自己的 chats,Agent 只能访问自己的 session,Knowledge 进入用户的个人 Knowledge)、
"shared"
(workspace 可见并共享)或
"isolated"
(私有,每个 tenant user 使用一个 workspace)。Private chats 需要 organization 的 private-session setting;如果未启用,SDK 会抛出
OpenGeniSetupError
,并指出应由谁启用。
chats
会设置
visibility
、
agentAccess
和
memoryScope
,这些字段也可作为显式 create fields 提供。Private sessions 不会让 workspace Files 或 Sites 变为私有,移除 tools 也不能替代 private visibility。未限定 scope 的 organization-key 所创建的顶层 sessions 对 workspace 可见。参阅
references/external-users-and-connect.md
。
外部 backend 负责产品 Skills。将它们存储并版本化在 OpenGeni 之外,然后为每个产品创建的 session 在
CreateSessionRequest.skills
中内联传入所选定义。该 integration contract 不提供 organization-wide Skill registry 或 Skill inheritance。
CreateSessionRequest.bundledSkillIds
用于收窄 OpenGeni 的内置指导,省略时使用 defaults,
[]
表示不使用任何内置指导;children、scheduled tasks 和 automations 也接受它。它不授予 tools,也不会隐藏 workspace 或 inline Skills。
新的 Skill input 需要有效的
SKILL.md
frontmatter,其中定义 name 和 description。不要将旧的、没有 header 的 Skills 作为新的 session input 重放。

Prompt And Context Contract

Prompt 和 Context 契约

Use each prompt surface for its exact authority and lifetime:
  • agent.identity
    (or the workspace's
    sessionAgentDefaults.identity
    ): who the agent is. It replaces only OpenGeni's introduction; older workspaces may still carry this in
    agentInstructions
    .
  • Workspace instructions (Knowledge > Instructions in the web app): stable workspace-wide rules.
  • Session
    instructions
    (the same field as
    agent.instructions
    ): durable refinement for one session. Instructions take priority over OpenGeni's default working style, never over its safety rules or how it runs tools.
  • modelContext
    : ordinary model-visible content attached to one exact user message as a separate history part; standard timeline rendering omits it.
  • initialMessage
    and later message text: the visible part of that user message.
modelContext
is not secret or privileged; full event/audit reads return it. Prefer concise per-message context plus authorized product tools over large snapshots, and never move it into instructions.
针对每种 prompt surface 的确切 authority 和 lifetime 使用它:
  • agent.identity
    (或 workspace 的
    sessionAgentDefaults.identity
    )定义 Agent 是谁。它只替换 OpenGeni 的 introduction;较旧的 workspaces 可能仍将其放在
    agentInstructions
    中。
  • Workspace instructions(Web app 中的 Knowledge > Instructions)是稳定的 workspace-wide rules。
  • Session
    instructions
    (与
    agent.instructions
    是同一字段)是单个 session 的持久化 refinement。Instructions 的优先级高于 OpenGeni 的默认 working style,但绝不高于其 safety rules 或 tools 的运行方式。
  • modelContext
    是附加到一条确切用户消息上的普通 model-visible 内容,作为独立 history part;标准 timeline rendering 会将其省略。
  • initialMessage
    和后续 message text 是该用户消息中可见的部分。
modelContext
不是 secret 或 privileged 内容;完整的 event/audit reads 会返回它。优先使用简洁的 per-message context 和已授权的产品 tools,而不是大型 snapshots,并且绝不将 context 移入 instructions。

Client Workflow

Client Workflow

  1. Load the server-held organization API key; resolve the authenticated product tenant, call
    ensureWorkspace
    , and persist the opaque workspace mapping.
  2. Read client config and access context without a Personal-workspace fallback.
  3. Create sessions with an explicit
    agent
    (capabilities and identity chosen for the product), the product-selected inline Skills, a stable idempotency key (optionally a preallocated ID), canonical resources, and the product's own tools. Omitted
    agent
    inherits the workspace defaults, which are normally everything the workspace offers.
  4. Serve the browser through the packaged proxy, or stream/replay through the SDK in a custom route; tolerate unknown additive event types.
  5. Send visible text separately from
    modelContext
    ; upload through the SDK helper, which owns begin, signed storage PUT, and completion.
  6. Surface approvals, human-input requests, queue state, errors, credit limits, and reconnect state as product state rather than generic chat text.
  7. Add realtime, Connected Machines, schedules, or the workbench only when the product use case needs them.
  1. 加载由服务端持有的 organization API key;解析已认证的产品 tenant,调用
    ensureWorkspace
    ,并持久化 opaque workspace mapping。
  2. 读取 client config 和 access context,不使用 Personal-workspace fallback。
  3. 创建 session 时明确提供
    agent
    (根据产品选择 capabilities 和 identity)、产品选择的 inline Skills、稳定的 idempotency key(可选用预先分配的 ID)、canonical resources 以及产品自己的 tools。省略
    agent
    会继承 workspace defaults,而后者通常包含 workspace 提供的一切能力。
  4. 通过打包的 proxy 为浏览器提供服务,或在自定义 route 中通过 SDK 进行 streaming/replay;容忍未知的 additive event types。
  5. 将 visible text 与
    modelContext
    分开发送;通过 SDK helper 上传文件,该 helper 负责 begin、signed storage PUT 和 completion。
  6. 将 approvals、human-input requests、queue state、errors、credit limits 和 reconnect state 呈现为产品状态,而不是普通 chat 文本。
  7. 仅在产品用例需要时添加 realtime、Connected Machines、schedules 或 workbench。

Guardrails

Guardrails

  • Workspace-scoped routes are canonical; resource IDs never authorize by themselves.
  • Organization workspaces have wire
    kind: "shared"
    ; Personal workspaces are outside the external product mapping.
  • Knowledge settings and prompt instructions never create a tenant boundary; tool removal is defense in depth, not authorization.
  • The SDK cannot accept arbitrary customer backend functions as remote tools. Expose an existing API through a reviewed OpenAPI/GraphQL Integration or an MCP server.
  • OpenGeni's credential broker encrypts secrets and keeps them out of model context, but the trusted control plane can decrypt them for the authorized provider request. Do not describe it as zero knowledge.
  • Do not call Temporal, NATS, Postgres, workers, sandbox providers, object storage APIs, or MCP transports as substitutes for the public SDK/API.
  • Do not claim auth, model, tool, billing, CORS, storage, or compute behavior until the live deployment or current source proves it. Credentials come from a secret manager or environment, never from examples or Skills.
  • Generate a customer-specific skill only for stable facts their coding agents repeatedly need. Keep it beside their integration code, point it at the SDK, include a config/access smoke probe, and never paste secrets into it. Start from
    references/customer-skill-template.md
    when the OpenGeni skill package is available.
  • Workspace-scoped routes 是标准入口;resource IDs 本身绝不能用于授权。
  • Organization workspaces 的 wire
    kind
    为
    "shared"
    ;Personal workspaces 不属于外部产品 mapping。
  • Knowledge settings 和 prompt instructions 永远不会创建 tenant boundary;移除 tools 是纵深防御,而不是授权机制。
  • SDK 无法将任意客户 backend functions 作为 remote tools 接收。通过经过审查的 OpenAPI/GraphQL Integration 或 MCP server 公开现有 API。
  • OpenGeni 的 credential broker 会加密 secrets,并使其不进入 model context,但受信任的 control plane 可以为已授权的 provider request 解密。绝不能将其描述为 zero knowledge。
  • 不要直接调用 Temporal、NATS、Postgres、workers、sandbox providers、object storage APIs 或 MCP transports 来替代公共 SDK/API。
  • 在 live deployment 或当前源码证明实际行为之前,不要声称 auth、model、tool、billing、CORS、storage 或 compute 行为已经成立。Credentials 只能来自 secret manager 或 environment,绝不能来自 examples 或 Skills。
  • 仅当客户编码 Agent 反复需要某些稳定事实时,才生成 customer-specific skill。将其放在客户的集成代码旁边,指向 SDK,包含 config/access smoke probe,并且绝不能将 secrets 粘贴到其中。如果可以使用 OpenGeni skill package,请从
    references/customer-skill-template.md
    开始。