@agent-native/dispatch 0.8.28 → 0.9.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 (42) hide show
  1. package/README.md +3 -1
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +6 -0
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/actions/provider-api-catalog.d.ts +3 -0
  6. package/dist/actions/provider-api-catalog.d.ts.map +1 -0
  7. package/dist/actions/provider-api-catalog.js +19 -0
  8. package/dist/actions/provider-api-catalog.js.map +1 -0
  9. package/dist/actions/provider-api-docs.d.ts +3 -0
  10. package/dist/actions/provider-api-docs.d.ts.map +1 -0
  11. package/dist/actions/provider-api-docs.js +26 -0
  12. package/dist/actions/provider-api-docs.js.map +1 -0
  13. package/dist/actions/provider-api-request.d.ts +3 -0
  14. package/dist/actions/provider-api-request.d.ts.map +1 -0
  15. package/dist/actions/provider-api-request.js +57 -0
  16. package/dist/actions/provider-api-request.js.map +1 -0
  17. package/dist/routes/pages/apps.d.ts.map +1 -1
  18. package/dist/routes/pages/apps.js +2 -1
  19. package/dist/routes/pages/apps.js.map +1 -1
  20. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  21. package/dist/server/lib/app-creation-store.js +9 -0
  22. package/dist/server/lib/app-creation-store.js.map +1 -1
  23. package/dist/server/lib/provider-api.d.ts +27 -0
  24. package/dist/server/lib/provider-api.d.ts.map +1 -0
  25. package/dist/server/lib/provider-api.js +24 -0
  26. package/dist/server/lib/provider-api.js.map +1 -0
  27. package/dist/server/plugins/agent-chat.d.ts.map +1 -1
  28. package/dist/server/plugins/agent-chat.js +1 -0
  29. package/dist/server/plugins/agent-chat.js.map +1 -1
  30. package/dist/server/plugins/integrations.d.ts.map +1 -1
  31. package/dist/server/plugins/integrations.js +1 -0
  32. package/dist/server/plugins/integrations.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/actions/index.ts +6 -0
  35. package/src/actions/provider-api-catalog.ts +27 -0
  36. package/src/actions/provider-api-docs.ts +35 -0
  37. package/src/actions/provider-api-request.ts +78 -0
  38. package/src/routes/pages/apps.tsx +2 -0
  39. package/src/server/lib/app-creation-store.ts +9 -0
  40. package/src/server/lib/provider-api.ts +42 -0
  41. package/src/server/plugins/agent-chat.ts +1 -0
  42. package/src/server/plugins/integrations.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-api.d.ts","sourceRoot":"","sources":["../../../src/server/lib/provider-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AAGzC,eAAO,MAAM,yBAAyB,kSAAmB,CAAC;AAC1D,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;AAgB1D,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,qBAAqB;;;;;;;;;;;;;;;IAEtE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,EAAE,qBAAqB,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,oBAEA;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,sBAAsB,oBAErE"}
@@ -0,0 +1,24 @@
1
+ import { PROVIDER_API_IDS, createProviderApiRuntime, } from "@agent-native/core/provider-api";
2
+ import { getCredentialContext } from "@agent-native/core/server";
3
+ export const DISPATCH_PROVIDER_API_IDS = PROVIDER_API_IDS;
4
+ const runtime = createProviderApiRuntime({
5
+ appId: "dispatch",
6
+ localCredentialSource: "dispatch_local",
7
+ getCredentialContext: () => {
8
+ const ctx = getCredentialContext();
9
+ if (!ctx) {
10
+ throw new Error("Dispatch provider API requests require an authenticated request context.");
11
+ }
12
+ return ctx;
13
+ },
14
+ });
15
+ export function listProviderApiCatalog(provider) {
16
+ return runtime.listCatalog(provider);
17
+ }
18
+ export function fetchProviderApiDocs(options) {
19
+ return runtime.fetchDocs(options);
20
+ }
21
+ export function executeProviderApiRequest(args) {
22
+ return runtime.executeRequest(args);
23
+ }
24
+ //# sourceMappingURL=provider-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-api.js","sourceRoot":"","sources":["../../../src/server/lib/provider-api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,wBAAwB,GAIzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CAAC;AAI1D,MAAM,OAAO,GAAG,wBAAwB,CAAC;IACvC,KAAK,EAAE,UAAU;IACjB,qBAAqB,EAAE,gBAAgB;IACvC,oBAAoB,EAAE,GAAG,EAAE;QACzB,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,sBAAsB,CAAC,QAAgC;IACrE,OAAO,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAIpC;IACC,OAAO,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,IAA4B;IACpE,OAAO,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC","sourcesContent":["import {\n PROVIDER_API_IDS,\n createProviderApiRuntime,\n type ProviderApiId,\n type ProviderApiMethod,\n type ProviderApiRequestArgs,\n} from \"@agent-native/core/provider-api\";\nimport { getCredentialContext } from \"@agent-native/core/server\";\n\nexport const DISPATCH_PROVIDER_API_IDS = PROVIDER_API_IDS;\nexport type DispatchProviderApiId = ProviderApiId;\nexport type { ProviderApiMethod, ProviderApiRequestArgs };\n\nconst runtime = createProviderApiRuntime({\n appId: \"dispatch\",\n localCredentialSource: \"dispatch_local\",\n getCredentialContext: () => {\n const ctx = getCredentialContext();\n if (!ctx) {\n throw new Error(\n \"Dispatch provider API requests require an authenticated request context.\",\n );\n }\n return ctx;\n },\n});\n\nexport function listProviderApiCatalog(provider?: DispatchProviderApiId) {\n return runtime.listCatalog(provider);\n}\n\nexport function fetchProviderApiDocs(options: {\n provider: DispatchProviderApiId;\n url?: string;\n maxBytes?: number;\n}) {\n return runtime.fetchDocs(options);\n}\n\nexport function executeProviderApiRequest(args: ProviderApiRequestArgs) {\n return runtime.executeRequest(args);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":";AAIA,wBAmCG"}
1
+ {"version":3,"file":"agent-chat.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":";AAIA,wBAoCG"}
@@ -31,6 +31,7 @@ Use the standard workspace primitives:
31
31
  - When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.
32
32
  - If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible "Starter", "Blank app", or "New app" UI behind.
33
33
  - Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
34
+ - Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.
34
35
 
35
36
  When a user asks for something like a digest, reminder, routing rule, or saved behavior:
36
37
  - First decide whether it should be a resource, a recurring job, a destination, or a delegated task.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat.js","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAe,qBAAqB,CAAC;IACnC,KAAK,EAAE,UAAU;IACjB,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,EAAE,eAAe;IACxB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;4EAqB4D;CAC3E,CAAC,CAAC","sourcesContent":["import { createAgentChatPlugin } from \"@agent-native/core/server\";\nimport { getOrgContext } from \"@agent-native/core/org\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nexport default createAgentChatPlugin({\n appId: \"dispatch\",\n // Without this, AGENT_ORG_ID is never set on agent action calls and every\n // row written through the frontend (vault secrets, destinations, workspace\n // resources) lands with org_id=NULL — breaking data isolation across orgs.\n resolveOrgId: async (event) => {\n const ctx = await getOrgContext(event);\n return ctx.orgId;\n },\n // Read actions directly from the package's own action map rather than from\n // a build-time-generated `.generated/actions-registry.ts` (the latter is a\n // template-only construct that the Vite plugin emits next to actions/).\n actions: dispatchActions,\n systemPrompt: `You are the central dispatch for this workspace.\n\nDefault posture:\n- Treat Slack and Telegram as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A when another app owns the job.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Prefer replying in the current external thread unless the user explicitly asks you to send to a saved destination.\n\nUse the standard workspace primitives:\n- Read and update resources like AGENTS.md, LEARNINGS.md, jobs/*.md, agents/*.md, and remote-agents/*.json when appropriate.\n- Use recurring jobs for scheduled behavior.\n- Use custom agent profiles in agents/*.md for local spawned work and remote-agents/*.json for remote A2A apps.\n- You receive a compact available-apps block with sibling workspace app names and descriptions. Use it to pick the right A2A target, and call list-connected-agents or tool-search only when you need fresh details.\n- When answering whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. If you have not requested that probe, absence of agent-card fields means unchecked, not unavailable.\n- When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n\nWhen a user asks for something like a digest, reminder, routing rule, or saved behavior:\n- First decide whether it should be a resource, a recurring job, a destination, or a delegated task.\n- Keep responses concise and operational.\n- Avoid inventing integrations or destinations that are not configured yet.`,\n});\n"]}
1
+ {"version":3,"file":"agent-chat.js","sourceRoot":"","sources":["../../../src/server/plugins/agent-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,eAAe,qBAAqB,CAAC;IACnC,KAAK,EAAE,UAAU;IACjB,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,2EAA2E;IAC3E,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,EAAE,eAAe;IACxB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;4EAsB4D;CAC3E,CAAC,CAAC","sourcesContent":["import { createAgentChatPlugin } from \"@agent-native/core/server\";\nimport { getOrgContext } from \"@agent-native/core/org\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nexport default createAgentChatPlugin({\n appId: \"dispatch\",\n // Without this, AGENT_ORG_ID is never set on agent action calls and every\n // row written through the frontend (vault secrets, destinations, workspace\n // resources) lands with org_id=NULL — breaking data isolation across orgs.\n resolveOrgId: async (event) => {\n const ctx = await getOrgContext(event);\n return ctx.orgId;\n },\n // Read actions directly from the package's own action map rather than from\n // a build-time-generated `.generated/actions-registry.ts` (the latter is a\n // template-only construct that the Vite plugin emits next to actions/).\n actions: dispatchActions,\n systemPrompt: `You are the central dispatch for this workspace.\n\nDefault posture:\n- Treat Slack and Telegram as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A when another app owns the job.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Prefer replying in the current external thread unless the user explicitly asks you to send to a saved destination.\n\nUse the standard workspace primitives:\n- Read and update resources like AGENTS.md, LEARNINGS.md, jobs/*.md, agents/*.md, and remote-agents/*.json when appropriate.\n- Use recurring jobs for scheduled behavior.\n- Use custom agent profiles in agents/*.md for local spawned work and remote-agents/*.json for remote A2A apps.\n- You receive a compact available-apps block with sibling workspace app names and descriptions. Use it to pick the right A2A target, and call list-connected-agents or tool-search only when you need fresh details.\n- When answering whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. If you have not requested that probe, absence of agent-card fields means unchecked, not unavailable.\n- When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.\n\nWhen a user asks for something like a digest, reminder, routing rule, or saved behavior:\n- First decide whether it should be a resource, a recurring job, a destination, or a delegated task.\n- Keep responses concise and operational.\n- Avoid inventing integrations or destinations that are not configured yet.`,\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,QAAA,MAAM,0BAA0B,GAAU,UAAU,GAAG,kBAuBtD,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,QAAA,MAAM,0BAA0B,GAAU,UAAU,GAAG,kBAuBtD,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
@@ -10,6 +10,7 @@ Default posture:
10
10
  - Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.
11
11
  - When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.
12
12
  - Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
13
+ - Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.
13
14
  - Keep durable memory and operating instructions in resources rather than ephemeral chat.
14
15
  - Reply in the originating thread unless the user explicitly asks you to send to a saved destination.
15
16
 
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;4FAsBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and assets (brand libraries plus generated images/videos).\n- Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.\n- If the user asks to create, build, make, scaffold, or generate an \"agent\" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode \"coming-soon\" or \"builder-unavailable\", explain the missing Builder setup and ask them to connect/configure Builder.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/server/plugins/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,kCAAkC,GAAG;;;;;;;;;;;;;;;;;;;;;;;4FAuBiD,CAAC;AAE7F;;;;GAIG;AACH,MAAM,0BAA0B,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE;IACzD,MAAM,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAClD,MAAM,cAAc,GAAG,YAAY,CAAC,YAAY,CAAC;IACjD,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,OAAO,cAAc,KAAK,UAAU;YACpC,CAAC,CAAC,cAAc,CAAC,kCAAkC,CAAC;YACpD,CAAC,CAAC,kCAAkC,CAAC;IAE3C,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,eAAe;QACxB,YAAY,EAAE,oBAAoB;QAClC,aAAa,EAAE,qBAAqB;QACpC,YAAY;QACZ,wDAAwD;QACxD,yEAAyE;QACzE,+DAA+D;QAC/D,6EAA6E;KAC9E,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,eAAe,0BAA0B,CAAC","sourcesContent":["import { createIntegrationsPlugin } from \"@agent-native/core/server\";\nimport {\n beforeDispatchProcess,\n resolveDispatchOwner,\n} from \"../lib/dispatch-integrations.js\";\nimport { getDispatchConfig } from \"../index.js\";\nimport { dispatchActions } from \"../../actions/index.js\";\n\nconst DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).\n\nDefault posture:\n- Treat Slack, Telegram, and email as shared entrypoints into the workspace.\n- Heavily delegate domain work to specialized agents through A2A (call-agent) when another app owns the job. Apps you can delegate to include slides (decks/presentations), analytics (data/dashboards), content (docs/articles), videos (Remotion compositions), forms (form builder), clips (screen recordings), design (visual designs), and assets (brand libraries plus generated images/videos).\n- Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.\n- When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.\n- Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.\n- Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.\n- Keep durable memory and operating instructions in resources rather than ephemeral chat.\n- Reply in the originating thread unless the user explicitly asks you to send to a saved destination.\n\nWhen a user asks for something:\n- If it belongs to analytics, content, slides, videos, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.\n- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.\n- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.\n- If the user asks to create, build, make, scaffold, or generate an \"agent\" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.\n- If a new-app prompt asks for access to Mail, Calendar, Analytics, Brain, Assets, or similar first-party app data/agents, keep using the existing hosted/connected app and A2A path. Do not ask Builder to scaffold those apps as children of the new app unless the user explicitly asks for a customized fork/copy.\n- If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible \"Starter\", \"Blank app\", or \"New app\" UI behind.\n- If the user explicitly asks for a new app or workspace app, call start-workspace-app-creation with their prompt and include a concise generated description by default. Do not satisfy a new-app request by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app. If the request is too vague to classify, ask one concise follow-up. If the action returns mode \"builder\", reply with the Builder branch URL; Builder is responsible for creating the separate workspace app under apps/<app-id>, mounting it at /<app-id>, ensuring apps/<app-id>/package.json exists with name/displayName and description so Dispatch discovers it, using relative /<app-id> links instead of hardcoded localhost/dev ports, and preserving APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() in the React Router client entry. The new app lives at the workspace root /<app-id>, NOT under /dispatch/<app-id>, /apps/<app-id>, or any other Dispatch tab — when telling the user where to find it, link to /<app-id> only. There is no separate workspace app registry to edit. If it returns mode \"local-agent\", tell the user it is ready for the local code agent and include the returned app path/prompt summary. If it returns mode \"coming-soon\" or \"builder-unavailable\", explain the missing Builder setup and ask them to connect/configure Builder.\n- For digests, reminders, or saved behavior, prefer recurring jobs, resources, or destinations over chat replies.\n- Keep responses concise and operational — messaging platforms have character limits.\n- Use markdown sparingly (bold and lists are fine, avoid complex formatting).\n- If a task requires many steps, summarize what you did rather than streaming every detail.`;\n\n/**\n * Defer plugin construction until the Nitro plugin actually fires so the\n * config-aware system prompt resolves AFTER `setupDispatch(config)` has\n * stamped the active config (plugin module load order is not guaranteed).\n */\nconst dispatchIntegrationsPlugin = async (nitroApp: any) => {\n const { integrations = {} } = getDispatchConfig();\n const promptOverride = integrations.systemPrompt;\n const systemPrompt =\n typeof promptOverride === \"string\"\n ? promptOverride\n : typeof promptOverride === \"function\"\n ? promptOverride(DISPATCH_INTEGRATION_SYSTEM_PROMPT)\n : DISPATCH_INTEGRATION_SYSTEM_PROMPT;\n\n const plugin = createIntegrationsPlugin({\n appId: \"dispatch\",\n actions: dispatchActions,\n resolveOwner: resolveDispatchOwner,\n beforeProcess: beforeDispatchProcess,\n systemPrompt,\n // Inherit the framework default (claude-sonnet-4-6 from\n // packages/core/src/integrations/plugin.ts). Haiku was tried for latency\n // but hallucinated URLs/IDs after delegated call-agent results\n // (e.g. inventing `https://slides.workspace.com/deck/builder-io-deck-2024`).\n });\n\n return plugin(nitroApp);\n};\n\nexport default dispatchIntegrationsPlugin;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.8.28",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
6
6
  "license": "MIT",
@@ -55,6 +55,9 @@ import openApp from "./open_app.js";
55
55
  import applyDreamProposal from "./apply-dream-proposal.js";
56
56
  import previewDreamProposal from "./preview-dream-proposal.js";
57
57
  import previewWorkspaceResourceChange from "./preview-workspace-resource-change.js";
58
+ import providerApiCatalog from "./provider-api-catalog.js";
59
+ import providerApiDocs from "./provider-api-docs.js";
60
+ import providerApiRequest from "./provider-api-request.js";
58
61
  import rejectDispatchChange from "./reject-dispatch-change.js";
59
62
  import rejectDreamProposal from "./reject-dream-proposal.js";
60
63
  import removePendingWorkspaceApp from "./remove-pending-workspace-app.js";
@@ -144,6 +147,9 @@ export const dispatchActions: Record<string, ActionEntry> = {
144
147
  "apply-dream-proposal": applyDreamProposal,
145
148
  "preview-dream-proposal": previewDreamProposal,
146
149
  "preview-workspace-resource-change": previewWorkspaceResourceChange,
150
+ "provider-api-catalog": providerApiCatalog,
151
+ "provider-api-docs": providerApiDocs,
152
+ "provider-api-request": providerApiRequest,
147
153
  "reject-dispatch-change": rejectDispatchChange,
148
154
  "reject-dream-proposal": rejectDreamProposal,
149
155
  "remove-pending-workspace-app": removePendingWorkspaceApp,
@@ -0,0 +1,27 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import {
4
+ DISPATCH_PROVIDER_API_IDS,
5
+ listProviderApiCatalog,
6
+ } from "../server/lib/provider-api.js";
7
+
8
+ const ProviderSchema = z.enum(DISPATCH_PROVIDER_API_IDS);
9
+
10
+ export default defineAction({
11
+ description:
12
+ "List raw HTTP API capabilities for shared workspace integrations and configured providers. Use before provider-api-request when grant/setup metadata is not enough and the provider's actual API must be inspected. Returns base URLs, auth style, credential key names, docs/spec URLs, placeholders, and examples; never returns secret values.",
13
+ schema: z.object({
14
+ provider: ProviderSchema.optional().describe(
15
+ "Optional provider id to inspect. Omit to list every provider API escape hatch.",
16
+ ),
17
+ }),
18
+ http: { method: "GET" },
19
+ readOnly: true,
20
+ run: async ({ provider }) => {
21
+ return {
22
+ providers: listProviderApiCatalog(provider),
23
+ guidance:
24
+ "Workspace integrations and grants are not capability limits. When a provider can answer a question through its HTTP API, inspect docs/spec URLs here and call provider-api-request with the exact provider API method/path/query/body instead of adding a rigid one-off action.",
25
+ };
26
+ },
27
+ });
@@ -0,0 +1,35 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import {
4
+ DISPATCH_PROVIDER_API_IDS,
5
+ fetchProviderApiDocs,
6
+ } from "../server/lib/provider-api.js";
7
+
8
+ const ProviderSchema = z.enum(DISPATCH_PROVIDER_API_IDS);
9
+
10
+ export default defineAction({
11
+ description:
12
+ "Inspect provider API docs/spec metadata, or fetch a registered provider docs/spec URL. Use this before arbitrary provider-api-request calls when the exact endpoint, filter operator, payload shape, pagination, or API version is uncertain.",
13
+ schema: z.object({
14
+ provider: ProviderSchema.describe(
15
+ "Provider whose API docs/spec to inspect.",
16
+ ),
17
+ url: z
18
+ .string()
19
+ .url()
20
+ .optional()
21
+ .describe(
22
+ "Optional docs/spec URL from provider-api-catalog to fetch. Only registered docs/spec origins are allowed.",
23
+ ),
24
+ maxBytes: z.coerce
25
+ .number()
26
+ .int()
27
+ .min(1_000)
28
+ .max(4 * 1024 * 1024)
29
+ .optional()
30
+ .describe("Maximum response bytes to read. Default 1MB, max 4MB."),
31
+ }),
32
+ http: { method: "GET" },
33
+ readOnly: true,
34
+ run: async (args) => fetchProviderApiDocs(args),
35
+ });
@@ -0,0 +1,78 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { z } from "zod";
3
+ import {
4
+ DISPATCH_PROVIDER_API_IDS,
5
+ executeProviderApiRequest,
6
+ } from "../server/lib/provider-api.js";
7
+
8
+ const ProviderSchema = z.enum(DISPATCH_PROVIDER_API_IDS);
9
+ const MethodSchema = z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"]);
10
+
11
+ export default defineAction({
12
+ description:
13
+ "Make an arbitrary authenticated HTTP request to a shared workspace integration or configured provider API. Use this as the flexible escape hatch when Dispatch needs a provider endpoint, filter, pagination mode, payload, or API version that no canned action models. The request is constrained to the provider host, uses configured credentials automatically, blocks private/internal URLs, and redacts secrets from responses.",
14
+ schema: z.object({
15
+ provider: ProviderSchema.describe(
16
+ "Configured provider API to call, e.g. slack, github, notion, hubspot, gmail, google_drive, google_calendar, granola, stripe, jira.",
17
+ ),
18
+ method: MethodSchema.default("GET").describe("HTTP method to use."),
19
+ path: z
20
+ .string()
21
+ .min(1)
22
+ .describe(
23
+ "Provider API path such as /search.messages, /repos/org/repo/issues, /crm/v3/objects/deals/search, or a full URL on an allowed provider host. Use placeholders from provider-api-catalog when provided.",
24
+ ),
25
+ query: z
26
+ .unknown()
27
+ .optional()
28
+ .describe(
29
+ "Optional query params as a JSON object/string. Array values produce repeated query params.",
30
+ ),
31
+ headers: z
32
+ .record(z.string(), z.unknown())
33
+ .optional()
34
+ .describe(
35
+ "Optional extra headers. Unsafe hop-by-hop headers are ignored. Auth headers are injected from stored credentials.",
36
+ ),
37
+ body: z
38
+ .unknown()
39
+ .optional()
40
+ .describe(
41
+ "Optional request body. Objects/arrays are JSON encoded; strings are sent as-is.",
42
+ ),
43
+ auth: z
44
+ .enum(["default", "none"])
45
+ .default("default")
46
+ .describe(
47
+ "Use default to inject configured provider auth. Use none only for public provider endpoints that intentionally require no auth.",
48
+ ),
49
+ connectionId: z
50
+ .string()
51
+ .optional()
52
+ .describe(
53
+ "Optional shared workspace connection id to use when the provider has multiple granted connections.",
54
+ ),
55
+ accountId: z
56
+ .string()
57
+ .optional()
58
+ .describe(
59
+ "Optional OAuth account id to use for OAuth-backed providers such as Gmail, Google Calendar, or Google Drive.",
60
+ ),
61
+ timeoutMs: z.coerce
62
+ .number()
63
+ .int()
64
+ .min(1_000)
65
+ .max(120_000)
66
+ .optional()
67
+ .describe("Request timeout in milliseconds. Default 30000, max 120000."),
68
+ maxBytes: z.coerce
69
+ .number()
70
+ .int()
71
+ .min(1_000)
72
+ .max(4 * 1024 * 1024)
73
+ .optional()
74
+ .describe("Maximum response bytes to read. Default 1MB, max 4MB."),
75
+ }),
76
+ http: false,
77
+ run: async (args) => executeProviderApiRequest(args),
78
+ });
@@ -8,6 +8,7 @@ import {
8
8
  IconChartBar,
9
9
  IconChevronDown,
10
10
  IconClipboardList,
11
+ IconContract,
11
12
  IconEyeOff,
12
13
  IconFileText,
13
14
  IconLoader2,
@@ -64,6 +65,7 @@ const TEMPLATE_ICONS: Record<string, typeof IconMail> = {
64
65
  Photo: IconPhoto,
65
66
  ChartBar: IconChartBar,
66
67
  ClipboardList: IconClipboardList,
68
+ Contract: IconContract,
67
69
  Brush: IconBrush,
68
70
  Video: IconVideo,
69
71
  };
@@ -1329,6 +1329,15 @@ const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
1329
1329
  colorRgb: "6 182 212",
1330
1330
  core: true,
1331
1331
  },
1332
+ {
1333
+ name: "contracts",
1334
+ label: "Contracts",
1335
+ hint: "Review assumptions, feedback, and proof for coding-agent work",
1336
+ icon: "Contract",
1337
+ color: "#4F46E5",
1338
+ colorRgb: "79 70 229",
1339
+ core: false,
1340
+ },
1332
1341
  {
1333
1342
  name: "design",
1334
1343
  label: "Design",
@@ -0,0 +1,42 @@
1
+ import {
2
+ PROVIDER_API_IDS,
3
+ createProviderApiRuntime,
4
+ type ProviderApiId,
5
+ type ProviderApiMethod,
6
+ type ProviderApiRequestArgs,
7
+ } from "@agent-native/core/provider-api";
8
+ import { getCredentialContext } from "@agent-native/core/server";
9
+
10
+ export const DISPATCH_PROVIDER_API_IDS = PROVIDER_API_IDS;
11
+ export type DispatchProviderApiId = ProviderApiId;
12
+ export type { ProviderApiMethod, ProviderApiRequestArgs };
13
+
14
+ const runtime = createProviderApiRuntime({
15
+ appId: "dispatch",
16
+ localCredentialSource: "dispatch_local",
17
+ getCredentialContext: () => {
18
+ const ctx = getCredentialContext();
19
+ if (!ctx) {
20
+ throw new Error(
21
+ "Dispatch provider API requests require an authenticated request context.",
22
+ );
23
+ }
24
+ return ctx;
25
+ },
26
+ });
27
+
28
+ export function listProviderApiCatalog(provider?: DispatchProviderApiId) {
29
+ return runtime.listCatalog(provider);
30
+ }
31
+
32
+ export function fetchProviderApiDocs(options: {
33
+ provider: DispatchProviderApiId;
34
+ url?: string;
35
+ maxBytes?: number;
36
+ }) {
37
+ return runtime.fetchDocs(options);
38
+ }
39
+
40
+ export function executeProviderApiRequest(args: ProviderApiRequestArgs) {
41
+ return runtime.executeRequest(args);
42
+ }
@@ -32,6 +32,7 @@ Use the standard workspace primitives:
32
32
  - When creating a new workspace app, create a separate app under apps/<app-id> with apps/<app-id>/package.json including a concise generated description, mount it at /<app-id>, use relative /<app-id> links, never hardcode localhost or dev ports, use shadcn/ui with @tabler/icons-react rather than lucide-react, and ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath(). There is no separate workspace app registry to edit.
33
33
  - If the starter template is used, treat it as scaffolding only: the finished app must be branded as the requested app with its own home screen/navigation/package metadata/manifest, and must not leave visible "Starter", "Blank app", or "New app" UI behind.
34
34
  - Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
35
+ - Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.
35
36
 
36
37
  When a user asks for something like a digest, reminder, routing rule, or saved behavior:
37
38
  - First decide whether it should be a resource, a recurring job, a destination, or a delegated task.
@@ -14,6 +14,7 @@ Default posture:
14
14
  - Use the available-apps prompt context first, then list-connected-agents when you need fresh details, to see what agents are available before assuming a request must be handled locally.
15
15
  - When asked whether workspace apps expose agent cards or A2A endpoints, call list-workspace-apps with includeAgentCards=true. Without that probe, missing agent-card fields mean unchecked, not unavailable.
16
16
  - Treat first-party apps such as Mail, Calendar, Analytics, Brain, Assets, and Dispatch as existing hosted/connected neighbors available through links and A2A/default connected agents. Do not create wrapper apps, child apps, nested routes, or cloned template copies just to give a new app access to them; build only the genuinely new workflow and delegate cross-app work to those existing apps.
17
+ - Integration grants are not provider capability limits. For ad hoc provider inspection, querying, reporting, or troubleshooting, call provider-api-catalog/provider-api-docs, then provider-api-request against the provider's real HTTP API. Use connectionId for a specific shared grant and accountId for a specific OAuth account. Never expose secret values or silently widen app access while doing this.
17
18
  - Keep durable memory and operating instructions in resources rather than ephemeral chat.
18
19
  - Reply in the originating thread unless the user explicitly asks you to send to a saved destination.
19
20