ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

鸿蒙6智能体开发实战:用DevEco Studio从零构建AI原生应用【开发者必读】

鸿蒙6智能体开发实战:用DevEco Studio从零构建AI原生应用【开发者必读】 1. 鸿蒙6智能体开发到底在做什么鸿蒙6智能体开发说白了就是让应用从“你点一下它动一下”变成“你说一句它自己规划”。AI原生应用的核心不是把大模型塞进 App 里做个聊天框而是让智能体具备意图理解、能力编排、上下文记忆这三件事。ArkUI 负责把交互做顺DevEco Studio 负责把工程骨架搭起来而真正让智能体“活”起来的是背后那套模型调用链路。适合谁看已经会写 ArkTS 页面、但没跑通过智能体闭环的鸿蒙开发者想把现有应用改造成 AI 原生的独立开发者以及需要给团队搭一套可复制工程模板的技术负责人。我试过最省事的路径是先用 DevEco Studio 建一个 Empty Ability 工程再把智能体能力层单独抽成一个 module页面只负责收发消息。这样后面换模型、加能力都不用动 UI。下面这套流程从拿 Key 到在模拟器里看到智能体回话全程可复制。2. 前置准备TaoToken 接入与工程初始化2.1 为什么智能体能力层要独立鸿蒙6的智能体架构里UI 层和能力层是解耦的。ArkUI 页面通过AgentClient发请求能力层负责拼 prompt、调模型、解析结构化输出。如果你把模型调用直接写在页面里后面加一个“日程解析”能力就要改页面维护成本会爆炸。所以第一步在 DevEco Studio 里新建工程后右键工程根目录 → New → Module → 选 Static Library命名agentcore。所有模型请求、prompt 模板、结果解析都放这里。2.2 获取 API Key智能体要调模型得先有凭证。打开 TaoToken 的 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite登录后点“创建密钥”复制那串sk-开头的字符串。注意这个 Key 只显示一次先粘到安全的地方。注意不要把 Key 硬编码进 ArkTS 源码再提交到代码仓库。后面我会用settings.json加环境变量的方式注入。2.3 工程目录结构建完后你的目录大概长这样SmartAgentDemo/ ├── entry/ # 主入口 HAP │ └── src/main/ets/ │ ├── pages/Index.ets # ArkUI 页面 │ └── entryability/ ├── agentcore/ # 智能体能力层 │ └── src/main/ets/ │ ├── AgentClient.ets # 请求封装 │ ├── PromptTemplates.ets │ └── types.ets ├── config/ │ └── config.toml # 模型与端点配置 └── settings.json # 本地密钥注入3. 可复制配置config.toml 与 settings.json3.1 config.toml 写什么config.toml放在工程根目录的config/下负责描述“用哪个模型、走哪个端点、超时多久”。ArkTS 侧用ohos.file.fs读它或者构建时用脚本转成常量。# config/config.toml [agent] name harmony6-smart-agent version 0.1.0 default_model claude-sonnet-4-5 [provider] base_url https://taotoken.net/api chat_path /v1/chat/completions timeout_ms 30000 max_retries 2 [models.claude] id claude-sonnet-4-5 max_tokens 2048 temperature 0.3 [models.gpt] id gpt-4o-mini max_tokens 1024 temperature 0.5 [capabilities] schedule true weather false reminder truebase_url用https://taotoken.net/api不要带 UTM 参数这是给程序调用的。temperature设 0.3 是因为智能体要输出结构化 JSON太随机会解析失败。3.2 settings.json 注入密钥settings.json放工程根目录只在本机存在加进.gitignore{ agent: { apiKey: sk-你的密钥粘这里, baseUrl: https://taotoken.net/api, defaultModel: claude-sonnet-4-5, logLevel: debug }, build: { injectEnv: true, envPrefix: AGENT_ } }DevEco Studio 的构建脚本会在编译时把apiKey读进BuildConfigArkTS 里通过BuildConfig.AGENT_API_KEY拿。这样源码里看不到明文。3.3 AgentClient 封装agentcore/src/main/ets/AgentClient.etsimport http from ohos.net.http; import { BuildConfig } from entry; export interface ChatMessage { role: system | user | assistant; content: string; } export interface AgentResponse { text: string; model: string; usage: { promptTokens: number; completionTokens: number }; } export class AgentClient { private baseUrl: string; private apiKey: string; private model: string; constructor() { this.baseUrl BuildConfig.AGENT_BASE_URL; this.apiKey BuildConfig.AGENT_API_KEY; this.model BuildConfig.AGENT_DEFAULT_MODEL; } async chat(messages: ChatMessage[]): PromiseAgentResponse { const httpRequest http.createHttp(); try { const resp await httpRequest.request(${this.baseUrl}/v1/chat/completions, { method: http.RequestMethod.POST, header: { Content-Type: application/json, Authorization: Bearer ${this.apiKey} }, extraData: JSON.stringify({ model: this.model, messages: messages, max_tokens: 2048, temperature: 0.3 }), connectTimeout: 30000, readTimeout: 30000 }); if (resp.responseCode ! 200) { throw new Error(HTTP ${resp.responseCode}: ${resp.result}); } const body JSON.parse(resp.result as string); return { text: body.choices[0].message.content, model: body.model, usage: { promptTokens: body.usage.prompt_tokens, completionTokens: body.usage.completion_tokens } }; } finally { httpRequest.destroy(); } } }关键点Authorization用 Bearer 格式extraData必须是字符串化的 JSON鸿蒙的 http 模块不会帮你序列化。4. ArkUI 页面与智能体对接4.1 页面状态设计entry/src/main/ets/pages/Index.ets里页面只维护三样东西消息列表、输入框内容、加载状态。import { AgentClient, ChatMessage } from agentcore; Entry Component struct Index { State messages: ChatMessage[] [ { role: system, content: 你是鸿蒙6智能体回答简洁涉及日程时输出 JSON。 } ]; State inputText: string ; State loading: boolean false; private client: AgentClient new AgentClient(); async sendMessage() { if (!this.inputText.trim() || this.loading) return; const userMsg: ChatMessage { role: user, content: this.inputText }; this.messages.push(userMsg); this.inputText ; this.loading true; try { const resp await this.client.chat(this.messages); this.messages.push({ role: assistant, content: resp.text }); } catch (e) { this.messages.push({ role: assistant, content: 请求失败${e.message} }); } finally { this.loading false; } } build() { Column() { List({ space: 12 }) { ForEach(this.messages, (msg: ChatMessage) { if (msg.role ! system) { ListItem() { Text(msg.content) .padding(12) .backgroundColor(msg.role user ? #D0E8FF : #F0F0F0) .borderRadius(8) .width(100%) } } }, (msg: ChatMessage) msg.content msg.role) } .layoutWeight(1) .width(100%) .padding(16) Row() { TextInput({ text: this.inputText, placeholder: 输入指令例如明天下午3点提醒我开会 }) .layoutWeight(1) .onChange((v: string) { this.inputText v; }) Button(this.loading ? ... : 发送) .onClick(() this.sendMessage()) .enabled(!this.loading) } .padding(16) .width(100%) } .width(100%) .height(100%) } }4.2 结构化输出解析智能体返回日程类指令时让它输出 JSON页面再解析。在 system prompt 里加一句涉及日程、提醒时只输出如下 JSON不要加解释 {action:create_reminder,time:ISO8601,content:...}解析代码function parseAgentAction(text: string): AgentAction | null { const match text.match(/\{[\s\S]*\}/); if (!match) return null; try { return JSON.parse(match[0]) as AgentAction; } catch { return null; } }这样页面就能根据action字段决定是弹提醒还是查天气而不是把整段文字直接显示。5. 在 DevEco Studio 中运行验证5.1 配置签名与模拟器打开 DevEco Studio → File → Project Structure → Signing Configs勾选 Automatically generate signature。然后 Tools → Device Manager启动一个 HarmonyOS 6 的 Phone 模拟器。5.2 运行并观察日志点绿色三角运行应用装到模拟器后在输入框敲明天下午3点提醒我开会预期结果列表里出现一条 assistant 消息内容是类似{action:create_reminder,time:2025-06-11T15:00:0008:00,content:开会}如果返回的是自然语言而不是 JSON说明 system prompt 没生效检查messages数组第一条是不是role: system。5.3 用模型对话页快速验证 Key在写代码之前想先确认 Key 和模型通不通可以直接打开模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite选claude-sonnet-4-5发一句“输出一个 JSON 格式的提醒”。能正常返回就说明凭证没问题再回到 DevEco Studio 排查工程侧。6. 本篇常见错排查6.1 报错 401 Unauthorized最常见的原因是 Key 没注入成功。检查settings.json里的apiKey是否被构建脚本读进BuildConfig。可以在AgentClient构造函数里加一行console.info(key prefix: this.apiKey.substring(0, 6))看日志里是不是sk-xxx。如果是空字符串说明injectEnv没生效检查build-profile.json5里有没有引用settings.json。6.2 报错 2300007 网络连接失败鸿蒙的 http 模块在模拟器里访问外网需要在module.json5里声明权限requestPermissions: [ { name: ohos.permission.INTERNET } ]漏了这行请求会直接抛 2300007而不是超时。6.3 返回内容被截断如果finish_reason是length说明max_tokens太小。在config.toml里把max_tokens调到 2048 或 4096。智能体输出 JSON 时容易超因为模型会先“思考”再输出。6.4 JSON 解析失败模型偶尔会在 JSON 前后加 json 代码块标记。解析前先做一次清洗function cleanJson(text: string): string { return text.replace(/json|/g, ).trim(); }6.5 模拟器里中文乱码ArkTS 的TextInput默认编码没问题但如果你的 prompt 模板文件是 GBK 保存的读进来会乱。统一用 UTF-8 保存所有.ets和.toml文件。7. 下一步从最小闭环到 Coding Plan跑通上面这套你已经有了一个能收发消息、能解析结构化输出的智能体骨架。接下来要加能力比如“查天气”“读日程”只需要在agentcore里加新的 prompt 模板和解析函数页面不用动。如果你打算把这个骨架用到长期编码或 Agent 项目里建议直接上 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite它按额度而不是按次计费适合频繁调试 prompt 的阶段。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面有各语言 SDK 的示例ArkTS 侧照着 http 封装改就行。最后留一个我踩过的坑鸿蒙的 http 模块在destroy()之后不能复用同一个实例每次请求都要createHttp()。如果你把 client 做成单例缓存 httpRequest第二次请求会直接失败。这个坑排查了我半小时希望你别再踩。
返回列表