diff --git a/extensions/feishu/src/chat-schema.ts b/extensions/feishu/src/chat-schema.ts index 5460f11dcc9..702773d4b73 100644 --- a/extensions/feishu/src/chat-schema.ts +++ b/extensions/feishu/src/chat-schema.ts @@ -9,6 +9,11 @@ export const FeishuChatSchema = Type.Object({ enum: [...CHAT_ACTION_VALUES], description: "Action to run: members | info | member_info", }), + accountId: Type.Optional( + Type.String({ + description: "Optional Feishu account override for multi-account setups", + }), + ), chat_id: Type.Optional(Type.String({ description: "Chat ID (from URL or event payload)" })), member_id: Type.Optional(Type.String({ description: "Member ID for member_info lookups" })), page_size: Type.Optional(Type.Number({ description: "Page size (1-100, default 50)" })), diff --git a/extensions/feishu/src/tool-account-routing.test.ts b/extensions/feishu/src/tool-account-routing.test.ts index 4b20d422037..af357838c7d 100644 --- a/extensions/feishu/src/tool-account-routing.test.ts +++ b/extensions/feishu/src/tool-account-routing.test.ts @@ -140,6 +140,23 @@ describe("feishu tool account routing", () => { expect(createFeishuClientMock.mock.calls.at(-1)?.[0]?.appId).toBe("app-b"); }); + test("chat tool allows explicit accountId override when defaultAccount disables chat", async () => { + chatGetMock.mockResolvedValue({ code: 0, data: { name: "chat", user_count: 1 } }); + const { api, resolveTool } = createToolFactoryHarness( + createConfig({ + defaultAccount: "b", + toolsA: { chat: true }, + toolsB: { chat: false }, + }), + ); + registerFeishuChatTools(api); + + const tool = resolveTool("feishu_chat", { agentAccountId: "a" }); + await tool.execute("call", { action: "info", chat_id: "oc_a", accountId: "a" }); + + expect(createFeishuClientMock.mock.calls.at(-1)?.[0]?.appId).toBe("app-a"); + }); + test("chat tool blocks execution when the routed account disables chat", async () => { const { api, resolveTool } = createToolFactoryHarness( createConfig({