AGENT SKILL

external-api-workflows

Build a Universal App workflow that calls a third-party API or custom model endpoint through a server-side function. Use for API keys, webhooks, Azure OpenAI-compatible endpoints, payment, messaging, or any provider credential that must stay out of the browser.

适用职业开发工程师
使用场景后端与接口
License 许可
MIT
所属仓库
microsoft/rayfin
最近更新
2026-10-30
Stars
★ 655
Forks
73

01 前言 Front Matter

name
external-api-workflows
description
Build a Universal App workflow that calls a third-party API or custom model endpoint through a server-side function. Use for API keys, webhooks, Azure OpenAI-compatible endpoints, payment, messaging, or any provider credential that must stay out of the browser.

03 SKILL.md 正文

External API workflows

Use a Rayfin function as the trust boundary between the UI and the external provider. Read functions-capability and apply its pack before implementing this workflow.

Secret contract

Declare only the secret name and a non-sensitive description in rayfin/rayfin.yml. Never put the value in YAML:

secrets:
  - name: THIRD_PARTY_API_KEY
    description: Credential used by the server-side fulfillment request.

Deploy the app once before provisioning the value. Obtain the user's confirmation for the target workspace and remote deployment. Read app-deployment and complete its version-matched Rayfin CLI workflow. The current secret command requires a deployed AppBackend endpoint.

Then ask the user to run:

npx rayfin secret set THIRD_PARTY_API_KEY

This command requires an interactive terminal for its masked prompt. If the host can spawn an independent interactive terminal, open it at the app root and start this command there so the masked prompt is immediately waiting. Do not claim that a terminal was opened unless the launch succeeded. Otherwise, pause and tell the user where to run the exact command. Do not pass the value through a non-interactive shell tool. The user enters the value directly into that command's masked prompt. Do not ask the user to paste a secret into chat. Do not place the value in source, YAML, frontend environment variables, command arguments, logs, or function output. Wait for the user to confirm that provisioning completed before invoking the deployed workflow.

After the value is provisioned, open the deployed fabricUrl and have the user invoke the workflow in the authenticated UI. Confirm that the UI receives only the bounded result contract. Do not report the workflow complete before this deployed invocation succeeds unless the user explicitly defers runtime validation.

Retrieve the production value only inside the function. The secret is declared with rayfin secret set, so it is typed — read it as a property:

const apiKey: string = ctx.Secrets.THIRD_PARTY_API_KEY;

ctx.Secrets.<NAME> is typed string, not string | undefined: declaring the secret is what makes it expected, and a name that was never declared is a compile error. If the value was not supplied at invoke time the read throws a diagnosable error rather than silently yielding undefined, so no SECRET_NOT_CONFIGURED branch is needed. Catch it at the function boundary if you want to map it onto the bounded result contract:

try {
  const apiKey: string = ctx.Secrets.THIRD_PARTY_API_KEY;
  // ...call the external service...
} catch {
  return {
    ok: false,
    code: 'SECRET_NOT_CONFIGURED',
    message: 'The external service credential is not configured.',
  };
}

Never hard-code the secret name anywhere else — it comes from rayfin.yml via the generated registry. ctx.getSecret('NAME') is deprecated and flagged by @typescript-eslint/no-deprecated; it remains valid only for a value deliberately not modelled in rayfin.yml.

Do not return apiKey, compare it against browser input, or include it in an exception. An environment fallback may be used only for local debugging through the functions project's ignored local settings.

Provider boundary

  • Do not call generic cloud or provider best-practices tools for a provider-neutral request. Use a provider-specific tool only after the user identifies that provider and the tool is needed to establish its contract.
  • Validate and bound every browser-supplied value before making a request.
  • Set an explicit outbound deadline appropriate for the provider.
  • Send only required headers and fields.
  • Treat non-success provider responses as expected domain outcomes when the UI can act on them.
  • Do not return raw provider bodies or stack traces.
  • Select and bound the provider fields returned to the browser.
  • Do not log the request body, response body, authorization header, secret, prompt, or user content.

Use a bounded result rather than exposing provider data directly:

type ExternalCallResult =
  | { ok: true; value: string }
  | {
      ok: false;
      code:
        | 'SECRET_NOT_CONFIGURED'
        | 'AUTHENTICATION_FAILED'
        | 'PROVIDER_REJECTED'
        | 'PROVIDER_TIMEOUT';
      message: string;
    };

Expected provider failures use the safe result. Unexpected failures may still throw, but the thrown message must not contain a secret, request body, raw provider response, or sensitive exception detail.

UI contract

Show an in-progress state for the complete invocation. Render safe, actionable outcomes for missing configuration, invalid authentication, provider rejection, and timeout. Keep an unexpected-failure state for failures outside the known domain result.

If the provider can take longer than the browser client's configured deadline, do not increase the global timeout for unrelated app operations. Use a dedicated client only as a documented temporary workaround until the SDK supports a per-invocation timeout.

04 同仓库更多 Skills

microsoft
microsoft/rayfin

rayfin-getting-started

Use when starting or creating a NEW Rayfin app, or when a Rayfin task comes up and you are not yet inside a Rayfin project. Gets you into a project with the Rayfin CLI, then hands off to the authoritative, version-locked in-project rayfin skill/docs that own all in-project work. Triggers: build a Rayfin app, start a Rayfin project, create a new Rayfin app, create-rayfin, npm create @microsoft/rayfin, rayfin init, scaffold rayfin, rayfin CLI, rayfin template, universal app, awesome-rayfin gallery, get started with Rayfin

★ 655
microsoft
microsoft/rayfin

visuals

Use when user wants to incorporate charts, graphs, data grid, or other visual representations of data into their project. Use VegaVisual and DataGrid components to create these visuals, utilizing the shared DataTable input, formatting, theme, and interactivity. Covers the onInteraction selection/click events host apps consume, named multi-table data input for layered overlays and reference lines, and Vega-Lite native selections. Triggers: chart, graph, plot, dashboard, KPI, metric, trend, scorecard, data grid, visualize.

数据分析师分析与可视化
★ 655
microsoft
microsoft/rayfin

schema-discovery

Explore Power BI semantic model schemas using DAX INFO functions. Progressive metadata discovery strategy, scope estimation, and narrowing techniques for tables, columns, measures, and relationships.

★ 655
microsoft
microsoft/rayfin

query-design

Separates DAX data-fetching from TypeScript presentation. Guides when to use DAX vs. TypeScript vs. Vega-Lite for aggregation, total rows, FORMAT(), SELECTCOLUMNS, BLANK handling, filtering, multi-grain queries, cross-filtering and cross-highlight subset/overlay queries, and format strings.

设计师演示文稿视觉设计
★ 655
microsoft
microsoft/rayfin

functions-capability

Apply and build the Universal App functions capability. Use for trusted server-side logic, secrets, external APIs, custom model endpoints, published Fabric data agents, webhooks, or privileged operations.

★ 655
microsoft
microsoft/rayfin

fabric-sdk

How to query Fabric data from a running app through the Rayfin connectors client. Use getRayfinClient().connectors.<name>.executeQuery to run DAX against a semantic model, and toQueryResult to normalize the response.

★ 655