关于 AI 函数调用和 MCP 的一切,Agentic AI 的关键词

2025-06-10

关于 AI 函数调用和 MCP 的一切,Agentic AI 的关键词

概括

阿特尼卡

在构建一个专门用于 AI 函数调用的 Agentic AI 框架的过程中,我们学习了很多关于函数调用的知识。本文将介绍我们在框架开发过程中关于函数调用的所有发现。

本文主要内容:

  1. 2023年,当OpenAI宣布AI函数调用时,许多人预测它将征服世界。然而,函数调用未能兑现这一承诺,并被代理工作流方法所掩盖。
  2. 我们找到了原因:对 JSON 模式缺乏理解,以及编译器级支持不足。代理框架应该强化基本的计算机科学原理,而不是专注于花哨的技术。
  3. OpenAPI 比 MCP 更古老且应用更广泛,当库开发人员对 JSON 模式有深入的理解并具备编译器技能时,它可以实现相同的目标。
  4. 通过使用我们的编排策略,函数调用可以提高性能,同时降低令牌成本,即使对于像gpt-4o-mini(8b) 这样的小模型也是如此。
  5. Agentica助力函数调用再创辉煌

1. 前言

函数调用

2023年,OpenAI宣布了AI函数调用。

当时,许多人工智能研究人员预测它将彻底改变整个行业。即使在我自己的网络中,也有许多开发人员争相构建以函数调用为中心的新型人工智能应用程序。

应用市场将围绕AI聊天机器人进行重组。

开发人员只需创建或收集 API 函数,AI 就会自动调用它们。无需再创建复杂的前端/客户端应用程序。

通过聊天做所有事情。

但今天又如何呢?函数调用已经征服了世界吗?没有——相比函数调用,代理工作流驱动开发已经成为了 AI 开发生态系统的主导。langchain也许是这个工作流生态系统中最具代表性的框架。

目前,许多人工智能开发者声称,人工智能函数调用难以实现,消耗过多的代币,并且经常导致幻觉。他们认为,为了使函数调用得到广泛应用,人工智能模型必须变得更便宜、更庞大、更智能。

然而,我们有不同的看法。如今的 LLM 已经足够强大,甚至可以支持更小的 8b 模型(可以在个人笔记本电脑上运行)。函数调用尚未得到广泛采用的原因是 AI 框架开发人员无法准确有效地构建函数模式。

他们没有足够重视计算机科学等基础知识,而是过度依赖华而不实的技术。

2.概念

2.1. AI函数调用

函数调用使 AI 模型能够通过识别何时调用函数并生成适当的 JSON 来调用该函数来与外部系统交互。

该模型不会生成自由格式的文本,而是根据用户请求识别何时调用特定函数,并为这些函数调用提供结构化数据。

2.2. 模型上下文协议

模型上下文协议

模型上下文协议 (MCP) 是一项开放标准,旨在促进 AI 工具与外部数据源之间的安全双向连接。该协议旨在简化 AI 助手与各种工具和数据的集成,从而实现更具动态性的交互。

MCP 标准化了聊天机器人等人工智能应用程序与外部系统交互的方式,使它们能够更有效地访问和利用数据。

它允许灵活且可扩展的集成,使开发人员更容易构建能够适应不同数据源和工具的应用程序。

2.3. 代理工作流程

代理工作流程

代理工作流是一种结构化的 AI 代理操作方法,其中多个专门的 AI 代理协同工作以完成复杂的任务。工作流中的每个代理都有特定的职责和专业知识,从而创建一个流程流水线,用于处理大型任务的不同方面。

顺便说一句,代理工作流主要针对特定​​用途的应用而设计,而非创建通用代理。代理工作流擅长解决边界清晰、定义明确的问题,将任务分解为需要不同专业知识的具体步骤。它们通常并非旨在创建一个“万能”的代理。

工作流驱动开发是当前AI开发的趋势,但用这种方法无法实现Agentic AI。当函数调用的效果不如预期时,它便应运而生了。

3. 功能架构

3.1. JSON Schema 规范

{
  name: "divide",
  arguments: {
    x: {
      type: "number",
    },
    y: {
      anyOf: [ // not supported in Gemini
        {
          type: "number",
          exclusiveMaximum: 0, // not supported in OpenAI and Gemini
        },
        {
          type: "number",
          exclusiveMinimum: 0, // not supported in OpenAI and Gemini
        },
      ],
    },
  },
  description: "Calculate x / y",
}
Enter fullscreen mode Exit fullscreen mode

你可能在人工智能社区里看到过这样的报道:

我创建了一个可以在 OpenAI GPT 上运行的函数模式,但它在 Google Gemini 上却无法运行。此外,我的一些函数模式在 Claude 上可以正常工作,但 OpenAI 却抛出异常,提示这是一个无效的模式。

实际上,不同 AI 供应商的 JSON 模式规范存在差异,有些供应商并不完全支持标准的 JSON 模式规范。例如,OpenAI 不支持 和minimum之类的约束属性format: uuid,而 Gemini 甚至不支持$ref和 之类的类型anyOf

具体来说,OpenAI 和 Gemini 拥有与标准不同的自定义 JSON 模式规范,而 Claude 则完全支持 JSON Schema 2020-12 草案。DeepSeek 和 Llama 等其他模型不限制 JSON 模式规范,允许使用标准 JSON 模式规范。

了解准确的 JSON 模式规范是从函数调用迈向 Agentic AI 的第一步。以下是各个 AI 供应商的 JSON 模式规范列表:

3.2. OpenAPI 和 MCP

import { HttpLlm, IHttpLlmApplication } from "@samchon/openapi";

const app: IHttpLlmApplication<"chatgpt"> = HttpLlm.application({
  model: "chatgpt",
  document: await fetch(
    "https://shopping-be.wrtn.ai/editor/swagger.json",
  ).then((r) => r.json()),
});
console.log(app);
Enter fullscreen mode Exit fullscreen mode

将 OpenAPI 文档转换为 AI 函数调用模式

💻 游乐场链接

类型 开放API 微胶囊钙
年龄 15年 6个月
生态系统 巨大的 微小的
参与者 每个 BE 开发人员 AI早期采用者

OpenAPI 文档为 API 函数提供了结构良好的规范,自 2010 年以来一直保持标准化和稳定。然而,它在 AI 函数调用生态系统中尚未得到广泛采用。与此同时,MCP(模型上下文协议)虽然是一种较新的协议,但却已被广泛采用。

就生态系统而言,OpenAPI 的文档数量远超 MCP,而且由于其长期以来作为后端开发者的标准而被广泛接受,其文档质量也更胜一筹。那么,为什么 OpenAPI 未能像 MCP 那样在 AI 生态系统中得到广泛接受呢?我们认为原因与上一章讨论的一样:精确模式问题。

如上所述,不同 AI 厂商的 JSON Schema 规范存在差异。此外,每个 OpenAPI 版本都有各自独特的 JSON Schema 规范。我们认为,这正是 OpenAPI 在函数调用生态系统中未能被广泛接受的原因。人们几乎不了解每个 AI 厂商的 JSON Schema 规范,又如何能指望他们将特定版本的 OpenAPI 文档转换为不同 AI 厂商的 JSON Schema 呢?相比之下,MCP 虽然是由 AI 生态系统中的一支重要力量 Anthropic Claude 推动的,但其规范简洁,无需单独的转换过程。这才是根本原因。

模式转换图

我们认为 MCP 是一个结构良好的协议,但我们也认为没有必要从 OpenAPI 迁移到 MCP 进行函数调用。OpenAPI 可以实现与 MCP 相同的目标,因此我们建议利用现有的 OpenAPI 生态系统。

为了支持从 OpenAPI 文档进行类似 MCP 的函数调用,我们正在将 Swagger/OpenAPI 文档转换为修订版的 OpenAPI v3.1 规范,删除歧义和重复的表达式。然后,我们使用与功能结构一致的迁移架构,将其转换为特定 AI 供应商的功能架构。

以下是将购物中心的 OpenAPI 文档转换为函数模式的演示代码,以及一段展示其作为实际 AI 代理运行的视频。只需swagger.json从现有的购物中心服务器导入该文件,即可通过聊天搜索商品、购买商品、管理配送、使用优惠券或处理退款。

理解、支持和利用 JSON 模式就是函数调用的全部内容。

import { Agentica, assertHttpLlmApplication } from "@agentica/core";
import OpenAI from "openai";

const agent = new Agentica({
  model: "chatgpt",
  vendor: {
    model: "gpt-4o-mini",
    api: new OpenAI({ apiKey: "********" }),
  },
  controllers: [
    {
      protocol: "http",
      name: "shopping",
      application: assertHttpLlmApplication({
        model: "chatgpt",
        document: await fetch(
          "https://shopping-be.wrtn.ai/editor/swagger.json",
        ).then((res) => res.json()),
      }),
      connection: {
        host: "https://shopping-be.wrtn.ai",
        headers: {
          Authorization: "Bearer ********",
        },
      },
    }
  ],
});
await agent.convert("I wanna buy a Macbook.");
Enter fullscreen mode Exit fullscreen mode

3.3. 编译器驱动开发

import { ILlmApplication } from "@samchon/openapi";
import typia, { tags } from "typia";

const app: ILlmApplication<"chatgpt"> = 
  typia.llm.application<BbsArticleService, "chatgpt">();
console.log(app);

class BbsArticleService {
  /**
   * Update an article.
   */
  update(props: {
    /**
     * Target article's {@link IBbsArticle.id}.
     */
    id: string & tags.Format<"uuid">;

    /**
     * New content to update.
     */
    input: IBbsArticle.IUpdate;
  }): void;
}
interface IBbsArticle { ... }
Enter fullscreen mode Exit fullscreen mode

💻 游乐场链接

了解不同 AI 供应商的 JSON 模式规范及其转换逻辑,是库或框架开发人员的主要要求。一个好的库应该允许用户只需提供函数或类即可调用 AI 函数,而无需了解 JSON 模式规范的复杂细节。

为了方便用户调用AI函数,并充分发挥Agentic AI的潜力,必须由编译器构建函数模式。如果无法以编程方式生成AI函数模式,函数调用将不可避免地被工作流代理方法所掩盖。

类型 价值
函数数量 289
源代码的 LOC 37,752
功能模式的 LOC 212,069
编译器成功率 100.00000%
人类成功率 0.00002%

例如,在上一节的商城后端演示中,AI 功能架构的代码行数(LOC)是源代码的 5.62 倍。如果要求用户手动编写 AI 功能架构,则需要投入比编写原始源代码多 5.62 倍的工作量。

源代码开发借助编译器和 IDE 的帮助,但 JSON 模式开发缺乏类似的支持,因此更容易出错。虽然人类前端开发人员可以直观地解决后端开发人员犯下的文档错误,但人工智能却无法容忍。即使是 AI 函数模式中的小错误,也可能破坏整个 AI 应用程序。

人工智能永远不会原谅

人工智能永远不会原谅模式错误

<?php
class BbsArticleController {
  /**
   * @OA\Post(
   *   path="/boards",
   *   tags={"BBS"},
   *   summary="Create a new article",
   *   description="Create a new article with its first snapshot",
   *   @OA\RequestBody(
   *     description="Article information to create",
   *     required=true,
   *     @OA\MediaType(
   *       mediaType="application/json",
   *       @OA\Schema(
   *         @OA\Property(
   *           property="title",
   *           type="string",
   *           description="Title of article",
   *         ),
   *         @OA\Property(
   *           property="content",
   *           type="string",
   *           description="Content body of article"
   *         ),
   *         @QA\Property(
   *           property="files",
   *           type="array",
   *           @QA\Items(
   *             @QA\Schema(
   *               @QA\Property(
   *                 property="name",
   *                 type="string",
   *                 maxLength=255,
   *                 description="File name, except the extension"
   *               ),
   *               @QA\Property(
   *                 property="extension",
   *                 type="string",
   *                 nullable=true,
   *                 maxLength=8,
   *                 description="File extension. If no extension, then set null"
   *               ),
   *               @QA\Property(
   *                 property="url",
   *                 type="string",
   *                 format="url",
   *                 description="URL address that the file is located in"
   *               )
   *             )
   *           )
   *         )
   *       )
   *     )
   *   ),
   *   @OA\Response(response="200", description="Success"),
   *   @OA\Response(response="400", description="Fail")
   * )
   */
  public function create(Request $request);
}
?>
Enter fullscreen mode Exit fullscreen mode

因此,AI功能模式必须由编译器构建。

如果您计划使用函数调用将后端服务器转换为 AI 代理,请避免使用需要开发人员手动编写 JSON 模式的语言和框架,例如PHP LaravelJava Spring RestDocs

相反,请使用编译器驱动(或基于反射)的 OpenAPI 文档生成器,例如NestiaFastAPI。然后使用库将编译器生成的 OpenAPI 转换为特定的 AI 函数模式@samchon/openapi,如下所示。

切勿手写 AI 功能模式。

import { HttpLlm, IHttpLlmApplication } from "@samchon/openapi";

const app: IHttpLlmApplication = HttpLlm.application({
  model: "claude",
  document: await fetch(
    "https://shopping-be.wrtn.ai/editor/swagger.json",
  ).then((r) => r.json()),
});
Enter fullscreen mode Exit fullscreen mode

3.4. 文档驱动开发

函数调用驱动的AI代理开发可以帮助开发者摆脱代理工作流开发的困难和缺乏灵活性,而专注于为每个函数提供详尽的文档。

观察许多其他声称函数调用和 MCP 未按预期工作的 AI 开发人员,我们发现他们通常没有在文档上投入足够的精力,这导致即使只有几个函数也会出现函数调用失败。

相比之下,我们的购物中心代理演示包含 289 个 API 函数,并且运行正常,没有出现任何重大问题。差异源于文档编写的投入程度。

以下是购物中心项目中文档的一个示例:

export function ShoppingSaleController<Actor extends IShoppingActorEntity>(
  props: IShoppingControllerProps,
) {
  @Controller(`shoppings/${props.path}/sales`)
  abstract class ShoppingSaleController {
    /**
     * List up every summarized sales.
     *
     * List up every {@link IShoppingSale.ISummary summarized sales}.
     *
     * As you can see, returned sales are summarized, not detailed. It does not
     * contain the SKU (Stock Keeping Unit) information represented by the
     * {@link IShoppingSaleUnitOption} and {@link IShoppingSaleUnitStock} types.
     * If you want to get such detailed information of a sale, use
     * `GET /shoppings/customers/sales/{id}` operation for each sale.
     *
     * > If you're an A.I. chatbot, and the user wants to buy or compose
     * > {@link IShoppingCartCommodity shopping cart} from a sale, please
     * > call the `GET /shoppings/customers/sales/{id}` operation at least once
     * > to the target sale to get detailed SKU information about the sale.
     * > It needs to be run at least once for the next steps.
     *
     * @param input Request info of pagination, searching and sorting
     * @returns Paginated sales with summarized information
     * @tag Sale
     *
     * @author Samchon
     */
    @TypedRoute.Patch()
    public index(
      @props.AuthGuard() actor: Actor,
      @TypedBody() input: IShoppingSale.IRequest,
    ): Promise<IPage<IShoppingSale.ISummary>>;

    /**
     * Get a sale with detailed information.
     *
     * Get a {@link IShoppingSale sale} with detailed information including
     * the SKU (Stock Keeping Unit) information represented by the
     * {@link IShoppingSaleUnitOption} and {@link IShoppingSaleUnitStock} types.
     *
     * > If you're an A.I. chatbot, and the user wants to buy or compose a
     * > {@link IShoppingCartCommodity shopping cart} from a sale, please call
     * > this operation at least once to the target sale to get detailed SKU
     * > information about the sale.
     * >
     * > It needs to be run at least once for the next steps. In other words,
     * > if you A.I. agent has called this operation to a specific sale, you
     * > don't need to call this operation again for the same sale.
     * >
     * > Additionally, please do not summarize the SKU information. Just show
     * > the every options and stocks in the sale with detailed information.
     *
     * @param id Target sale's {@link IShoppingSale.id}
     * @returns Detailed sale information
     * @tag Sale
     *
     * @author Samchon
     */
    @TypedRoute.Get(":id")
    public at(
      @props.AuthGuard() actor: Actor,
      @TypedParam("id") id: string & tags.Format<"uuid">,
    ): Promise<IShoppingSale>;
  }
  return ShoppingSaleController;
}
Enter fullscreen mode Exit fullscreen mode

在编写函数描述时,需要清晰、详尽地描述每个函数的用途。如果函数之间存在关系(例如先决条件),也必须进行描述。

/**
 * Final component information on units for sale.
 *
 * `IShoppingSaleUnitStock` is a subsidiary entity of {@link IShoppingSaleUnit}
 * that represents a product catalog for sale, and is a kind of final stock that is
 * constructed by selecting all {@link IShoppingSaleUnitSelectableOption options}
 * (variable "select" type) and their
 * {@link IShoppingSaleUnitOptionCandidate candidate} values in the belonging unit.
 * It is the "good" itself that customers actually purchase.
 *
 * - Product Name) MacBook
 *   - Options
 *     - CPU: { i3, i5, i7, i9 }
 *     - RAM: { 8GB, 16GB, 32GB, 64GB, 96GB }
 *     - SSD: { 256GB, 512GB, 1TB }
 *   - Number of final stocks: 4 * 5 * 3 = 60
 *
 * For reference, the total number of `IShoppingSaleUnitStock` records in an
 * attribution unit can be obtained using Cartesian Product. In other words, the
 * value obtained by multiplying all the candidate values that each
 * (variable "select" type) option can have by the number of cases is the total
 * number of final stocks in the unit.
 *
 * Of course, without a single variable "select" type option, the final stocks
 * count in the unit is only 1.
 *
 * @author Samchon
 */
export interface IShoppingSaleUnitStock { ... }
Enter fullscreen mode Exit fullscreen mode

描述类型的时候,写成ERD(实体关系图)描述。

import { tags } from "typia";

/**
 * Restriction information of the coupon.
 *
 * @author Samchon
 */
export interface IShoppingCouponRestriction {
  /**
   * Access level of coupon.
   *
   * - public: possible to find from public API
   * - private: unable to find from public API
   *   - arbitrarily assigned by the seller or administrator
   *   - issued from one-time link
   */
  access: "public" | "private";

  /**
   * Exclusivity or not.
   *
   * An exclusive discount coupon refers to a discount coupon that has an
   * exclusive relationship with other discount coupons and can only be
   * used alone. That is, when an exclusive discount coupon is used, no
   * other discount coupon can be used for the same
   * {@link IShoppingOrder order} or {@link IShoppingOrderGood good}.
   *
   * Please note that this exclusive attribute is a very different concept
   * from multiplicative, which means whether the same coupon can be
   * multiplied and applied to multiple coupons of the same order, so
   * please do not confuse them.
   */
  exclusive: boolean;

  /**
   * Limited quantity issued.
   *
   * If there is a limit to the quantity issued, it becomes impossible
   * to issue tickets exceeding this value.
   *
   * In other words, the concept of N coupons being issued on
   * a first-come, first-served basis is created.
   */
  volume: null | (number & tags.Type<"uint32">);

  /**
   * Limited quantity issued per person.
   *
   * As a limit to the total amount of issuance per person, it is
   * common to assign 1 to limit duplicate issuance to the same citizen,
   * or to use the NULL value to set no limit.
   *
   * Of course, by assigning a value of N, the total amount issued
   * to the same citizen can be limited.
   */
  volume_per_citizen: null | (number & tags.Type<"uint32">);

  /**
   * Expiration day(s) value.
   *
   * The concept of expiring N days after a discount coupon ticket is issued.
   *
   * Therefore, customers must use the ticket within N days, if possible,
   * from the time it is issued.
   */
  expired_in: null | (number & tags.Type<"uint32">);

  /**
   * Expiration date.
   *
   * A concept that expires after YYYY-MM-DD after a discount coupon ticket
   * is issued.
   *
   * Double restrictions are possible with expired_in, of which the one
   * with the shorter expiration date is used.
   */
  expired_at: null | (string & tags.Format<"date-time">);
}
Enter fullscreen mode Exit fullscreen mode

不要忘记描述属性。

4. 编排策略

编排策略

4.1. 选择器,确定要调用的候选函数

过滤候选函数以减少上下文。

如果你把 Github MCP 服务器带到 Claude Desktop,它在很多情况下很可能会崩溃。这是因为 Github MCP 服务器有 30 个函数,而 Claude Desktop 会直接一次性列出所有这些函数给代理。过多的函数会产生过多的上下文,导致幻觉。

为了避免这种幻觉,我们创建了一个选择器代理,它会根据每个函数的名称和描述来选择要调用的候选函数。只有选择器代理选择的候选函数才会呈现给主代理,以确保函数上下文不会像 Claude Desktop 那样变得过于复杂。

在选择候选功能时,选择代理还会提供选择理由。此外,由于选择代理可以删除不再需要的候选功能,因此候选功能列表通常不超过四个。

Github MCP 太多,很多都崩溃了

增强函数调用后的Agentica可以正常工作

4.2. 带有验证反馈的调用者

函数调用并不完美,因此验证反馈至关重要。

选择器代理完成工作后,调用器代理会将候选函数提交给主代理进行实际的函数调用。然而,调用器代理还有一项额外的责任:验证反馈。

验证反馈是一种纠正错误类型参数的策略。如果AI代理在为函数调用编写参数时出错,调用方代理会提供详细的类型错误信息,以便代理在后续尝试中纠正错误。

例如,在购物中心代理演示中,当使用购物车购买商品时ShoppingCartCommodity,AI代理的错误率约为60%。如果没有验证反馈,函数调用驱动的AI代理就无法可靠地运行。

姓名 地位
ObjectConstraint 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ObjectFunctionSchema 2️⃣2️⃣4️⃣2️⃣2️⃣2️⃣2️⃣2️⃣5️⃣2️⃣
ObjectHierarchical 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣2️⃣1️⃣1️⃣2️⃣
ObjectJsonSchema 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ObjectSimple 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ObjectUnionExplicit 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ObjectUnionImplicit 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ShoppingCartCommodity 1️⃣2️⃣2️⃣3️⃣1️⃣1️⃣4️⃣2️⃣1️⃣2️⃣
ShoppingOrderCreate 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ShoppingOrderPublish 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣❌1️⃣1️⃣1️⃣
ShoppingSaleDetail 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣
ShoppingSalePage 1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣1️⃣

值 1 表示函数调用成功,无需验证反馈。

其他值表示需要多少验证反馈。

4.3. 描述者

描述代理只是将函数调用的返回值描述为markdown内容。

如果要增强可视化效果,可以将函数调用的返回值更改为特定的UI组件。

此外,如果您想为每个功能制作特定的可视化组件,但又没有足够的时间,请考虑使用我们的另一个框架AutoView,它可以从模式信息生成 TypeScript 前端代码。

如果你有 100 个 TypeScript 函数,那么你可以编写 100 个前端组件的源代码。或者,如果你有 200 个 API 函数,那么你可以为每个 API 函数编写 200 个 UI 组件的源代码。

AutoView 游乐场

5. Agentica框架

Agentica 是一个专门用于 LLM 函数调用的 Agentic AI 框架。

我们自 2023 年以来研究并在本文中分享的所有知识都已纳入 Agentica 框架。

只需列出功能,即可创建任何所需的代理。只需管理功能列表,即可让您的代理灵活、可扩展且高效。

import { Agentica, assertHttpLlmApplication } from "@agentica/core";
import OpenAI from "openai";
import typia from "typia";

const agent = new Agentica({
  vendor: {
    model: "gpt-4o-mini",
    api: new OpenAI({ apiKey: "********" }),
  },
  controllers: [
    // Functions from OpenAPI Document
    assertHttpLlmApplication({
      model: "chatgpt",
      document: await fetch(
        "https://shopping-be.wrtn.ai/editor/swagger.json",
      ).then(r => r.json()),
      connection: {
        host: "https://shopping-be.wrtn.ai",
        headers: {
          Authorization: "Bearer ********",
        },
      },
    }),
    // Functions from TypeScript Classes
    {
      protocol: "class",
      application: typia.llm.application<MobileCamera, "chatgpt">(),
      execute: new MobileCamera(),
    },
    {
      protocol: "class",
      application: typia.llm.application<MobileFileSystem, "chatgpt">(),
      execute: new MobileFileSystem(),
    },
  ],
});
await agent.conversate("I want to write an article.");
Enter fullscreen mode Exit fullscreen mode

鏂囩珷鏉ユ簮锛�https://dev.to/samchon/everything-about-ai-function-calling-mcp-the-keyword-for-agentic-ai-2id7
PREV
[Typia] 我制作了实时演示网站,验证速度提高了 20,000 倍(JSON 字符串化速度提高了 200 倍)
NEXT
[Agentica] 每个后端开发人员都是优秀的 AI 开发人员