---
id: "6b6d8ab85fca49bb73d4"
url: "https://www.xmcsl.cn/project/feishu-cli-embed/02-one-click-app/05-%E4%B8%80%E9%94%AE%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8%EF%BC%88Go%EF%BC%89.html"
source_url: "https://open.feishu.cn/document/mcp_open_tools/integrating-agents-with-feishu/create-an-app-in-one-click-go"
source_date: null
checked_at: "2026-11-05T04:21:48.909937+00:00"
status: "ready"
check_scope: "structure_only; not a factual or human review"
body_sha256: "ff77bad96b90be063d6331eb8763899d86a0de0318c794f794fd9eeb4636560d"
---

# 一键创建应用（Go） · 飞书 Agent 接入知识库

Go SDK 提供了 <code>RegisterApp</code> 方法，基于 OAuth 2.0 Device Authorization Grant（RFC 8628）协议实现一键创建应用。

 

调用该方法会返回一个验证链接，用户在飞书或 Lark 中打开该链接（或扫码）完成授权后，即可自动注册应用并获取凭据（App ID 和 App Secret），无需手动前往开发者后台创建。

 

查看源码：<a href="https://github.com/larksuite/oapi-sdk-go#%E4%B8%80%E9%94%AE%E5%88%9B%E5%BB%BA%E5%BA%94%E7%94%A8--one-click-app-registration">oapi-sdk-go</a>

 

## 前提条件

 

<ul>&#10;<li>安装 <code>oapi-sdk-go</code>，且 SDK 版本为最新 v3 版本。</li>&#10;</ul>

 

```shell
  go get github.com/larksuite/oapi-sdk-go/v3@latest
```

 

## 快速开始示例

 

```go
package main

import (
    "context"
    "errors"
    "fmt"
    "time"

lark "github.com/larksuite/oapi-sdk-go/v3"
    "github.com/larksuite/oapi-sdk-go/v3/scene/registration"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
    defer cancel()

result, err := registration.RegisterApp(ctx, &registration.Options{
        OnQRCode: func(info *registration.QRCodeInfo) {
            fmt.Printf("open or scan this url: %s\n", info.URL)
            fmt.Printf("the link expires in %d seconds\n", info.ExpireIn)
        },
        OnStatusChange: func(info *registration.StatusChangeInfo) {
            // status: polling | slow_down | domain_switched
            fmt.Printf("registration status: %s", info.Status)
            if info.Interval > 0 {
                fmt.Printf(", next poll after %d seconds", info.Interval)
            }
            fmt.Println()
        },
    })
    if err != nil {
        var regErr *registration.RegisterAppError
        if errors.As(err, &regErr) {
            fmt.Printf("register app failed: code=%s, description=%s\n", regErr.Code, regErr.Description)
            return
        }
        panic(err)
    }

fmt.Println("App ID:", result.ClientID)
    fmt.Println("App Secret:", result.ClientSecret)

client := lark.NewClient(result.ClientID, result.ClientSecret)
    _ = client
}
```

 

## 自定义权限、事件、回调与更新已有应用

 

创建应用时，可通过 <code>Options.Addons</code> 在平台基础模板上增量申请权限、事件订阅和回调。这些配置会预填到用户扫码后的确认页中，用户确认后生效。<code>Options.CreateOnly=true</code> 时，页面只允许创建新应用；传入 <code>Options.AppID</code> 时，页面会进入更新已有应用配置的确认流程。

 

```go
_, err := registration.RegisterApp(ctx, &registration.Options{
    Addons: &registration.AppAddons{
        Scopes: registration.AppAddonsScopes{
            Tenant: []string{"im:message:send_as_bot"},
            User:   []string{"calendar:calendar:read"},
        },
        Events: registration.AppAddonsEvents{
            Items: registration.AppAddonsEventItems{
                Tenant: []string{"im.message.receive_v1"},
            },
        },
        Callbacks: registration.AppAddonsCallbacks{
            Items: []string{"card.action.trigger"},
        },
    },
    CreateOnly: true,
    OnQRCode: func(info *registration.QRCodeInfo) {
        fmt.Println(info.URL)
    },
})
if err != nil {
    panic(err)
}

_, err = registration.RegisterApp(ctx, &registration.Options{
    AppID: "cli_xxx",
    Addons: &registration.AppAddons{
        Scopes: registration.AppAddonsScopes{
            Tenant: []string{"drive:drive.metadata:readonly"},
        },
    },
    OnQRCode: func(info *registration.QRCodeInfo) {
        fmt.Println(info.URL)
    },
})
if err != nil {
    panic(err)
}
```

 

注意：<code>Addons</code> 仅支持增量叠加，不支持删除基础模板中的配置；SDK 只校验数据形状和非空字符串，不校验权限点、事件或回调名称是否存在。

 

### 通过 <code>Preset</code> 选择模板底座

 

<code>AppAddons.Preset</code> 用于选择应用创建的模板底座（与 <code>Options.AppPreset</code> 无关，后者只预填应用名称、描述和头像）：

 

<table>&#10;<thead>&#10;<tr>&#10;<th>取值</th>&#10;<th>模板底座</th>&#10;<th>行为</th>&#10;</tr>&#10;</thead>&#10;<tbody>&#10;<tr>&#10;<td>不设置（<code>nil</code>）</td>&#10;<td>平台默认模板</td>&#10;<td>与该字段出现之前完全一致；编码后的 payload 不含 <code>preset</code> 键。</td>&#10;</tr>&#10;<tr>&#10;<td><code>false</code></td>&#10;<td>最小基础模板</td>&#10;<td>确认页只展示 <code>Addons</code> 中显式声明的权限、事件和回调。</td>&#10;</tr>&#10;<tr>&#10;<td><code>true</code></td>&#10;<td>平台默认模板</td>&#10;<td>显式声明使用默认底座，效果与不设置相同。</td>&#10;</tr>&#10;</tbody>&#10;</table>

 

<code>Preset</code> 为 <code>false</code> 时，允许 <code>Addons</code> 不携带任何权限、事件或回调——页面仍会进入确认流程，创建仅含最小底座能力的应用：

 

```go
preset := false
_, err := registration.RegisterApp(ctx, &registration.Options{
    Addons: &registration.AppAddons{
        Preset: &preset,
    },
    OnQRCode: func(info *registration.QRCodeInfo) {
        fmt.Println(info.URL)
    },
})
if err != nil {
    panic(err)
}
```

 

## registration.RegisterApp 参数

 

<table>&#10;<thead>&#10;<tr>&#10;<th>参数</th>&#10;<th>描述</th>&#10;<th>类型</th>&#10;<th>必填</th>&#10;<th>默认值</th>&#10;</tr>&#10;</thead>&#10;<tbody>&#10;<tr>&#10;<td><code>ctx</code></td>&#10;<td>控制注册流程的超时与取消；取消 <code>context</code> 会终止轮询。</td>&#10;<td><code>context.Context</code></td>&#10;<td>是</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Source</code></td>&#10;<td>来源标识，会拼入二维码 URL 的 <code>source</code> 参数，格式为 <code>go-sdk/&#123;source&#125;</code>。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td><code>go-sdk</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Domain</code></td>&#10;<td>自定义飞书认证域名，支持传完整前缀，如 <code>https://accounts.feishu.cn</code>。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td><code>https://accounts.feishu.cn</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.LarkDomain</code></td>&#10;<td>自定义 Lark 认证域名；检测到 <code>tenant&#95;brand=lark</code> 时自动切换。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td><code>https://accounts.larksuite.com</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.AppPreset</code></td>&#10;<td>预设应用信息，仅用于初始化创建页；用户仍可在页面修改，最终以页面提交为准。</td>&#10;<td><code>&#42;registration.AppPreset</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.AppPreset.Avatar</code></td>&#10;<td>应用头像 URL，支持 1-6 个；第一个默认选中。传原始 URL，SDK 会编码。头像展示、图片可访问性、GIF 取帧等由创建页处理。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.AppPreset.Name</code></td>&#10;<td>应用名称，支持 <code>&#123;user&#125;</code> 占位符；传原始值，SDK 会编码。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.AppPreset.Desc</code></td>&#10;<td>应用描述，支持 <code>&#123;user&#125;</code> 占位符；传原始值，SDK 会编码。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons</code></td>&#10;<td>增量权限、事件、回调配置，预填到扫码后的确认页，用户确认后生效。</td>&#10;<td><code>&#42;registration.AppAddons</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Preset</code></td>&#10;<td>模板底座选择：不设置为平台默认模板；<code>false</code> 为最小基础模板（此时允许增量为空）；<code>true</code> 为显式声明默认底座。</td>&#10;<td><code>&#42;bool</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Scopes.Tenant</code></td>&#10;<td>应用身份权限列表，如 <code>im:message:send&#95;as&#95;bot</code>。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Scopes.User</code></td>&#10;<td>用户身份权限列表，如 <code>calendar:calendar:read</code>。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Events.Items.Tenant</code></td>&#10;<td>应用身份事件列表，如 <code>im.message.receive&#95;v1</code>。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Events.Items.User</code></td>&#10;<td>用户身份事件列表，如 <code>calendar.calendar.event.changed&#95;v4</code>。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.Addons.Callbacks.Items</code></td>&#10;<td>回调列表，如 <code>card.action.trigger</code>。</td>&#10;<td><code>&#91;&#93;string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.CreateOnly</code></td>&#10;<td>为 <code>true</code> 时落地页仅允许创建新应用；与 <code>Options.AppID</code> 同时传入时，页面侧优先走新建流程。</td>&#10;<td><code>bool</code></td>&#10;<td>否</td>&#10;<td><code>false</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.AppID</code></td>&#10;<td>已有应用的 App ID；传入后会作为二维码 URL 的 <code>clientID</code> 参数，用于更新已有应用配置。</td>&#10;<td><code>string</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.OnQRCode</code></td>&#10;<td>验证链接就绪时的回调，参数为 <code>&#123; URL, ExpireIn &#125;</code>。可直接展示链接，或将其渲染为二维码供用户扫码。</td>&#10;<td><code>func(info &#42;registration.QRCodeInfo)</code></td>&#10;<td>是</td>&#10;<td>-</td>&#10;</tr>&#10;<tr>&#10;<td><code>Options.OnStatusChange</code></td>&#10;<td>轮询状态变化回调，参数为 <code>&#123; Status, Interval &#125;</code>。<code>Status</code> 可能为 <code>polling</code>、<code>slow&#95;down</code>、<code>domain&#95;switched</code>。</td>&#10;<td><code>func(info &#42;registration.StatusChangeInfo)</code></td>&#10;<td>否</td>&#10;<td>-</td>&#10;</tr>&#10;</tbody>&#10;</table>

 

## 返回值

 

<table>&#10;<thead>&#10;<tr>&#10;<th>字段</th>&#10;<th>类型</th>&#10;<th>描述</th>&#10;</tr>&#10;</thead>&#10;<tbody>&#10;<tr>&#10;<td><code>ClientID</code></td>&#10;<td><code>string</code></td>&#10;<td>应用的 <code>App ID</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>ClientSecret</code></td>&#10;<td><code>string</code></td>&#10;<td>应用的 <code>App Secret</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>UserInfo</code></td>&#10;<td><code>&#42;registration.UserInfo</code></td>&#10;<td>扫码用户信息</td>&#10;</tr>&#10;<tr>&#10;<td><code>UserInfo.OpenID</code></td>&#10;<td><code>string</code></td>&#10;<td>扫码用户的 <code>open&#95;id</code></td>&#10;</tr>&#10;<tr>&#10;<td><code>UserInfo.TenantBrand</code></td>&#10;<td><code>string</code></td>&#10;<td><code>"feishu"</code> 或 <code>"lark"</code></td>&#10;</tr>&#10;</tbody>&#10;</table>

 

## 错误处理

 

返回的错误通常可以通过 <code>errors.As(err, &amp;registration.RegisterAppError)</code> 获取 <code>Code</code> 与 <code>Description</code> 字段。更具体的错误类型还包括 <code>registration.AccessDeniedError</code> 和 <code>registration.ExpiredError</code>。

 

<table>&#10;<thead>&#10;<tr>&#10;<th><code>Code</code></th>&#10;<th>描述</th>&#10;</tr>&#10;</thead>&#10;<tbody>&#10;<tr>&#10;<td><code>access&#95;denied</code></td>&#10;<td>用户拒绝授权</td>&#10;</tr>&#10;<tr>&#10;<td><code>expired&#95;token</code></td>&#10;<td>二维码过期或轮询超时</td>&#10;</tr>&#10;<tr>&#10;<td><code>invalid&#95;response</code></td>&#10;<td>接口返回缺少必要字段或响应为空</td>&#10;</tr>&#10;</tbody>&#10;</table>
