Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b53b718
docs: add agent tools expansion design spec
NadavAvraham May 13, 2026
e4be478
docs: add agent tools expansion implementation plan
NadavAvraham May 13, 2026
a75204b
refactor(agent-toolkit): export agentFieldsFragment for reuse
NadavAvraham May 13, 2026
ec0d01b
feat(agent-toolkit): add GraphQL operations for 6 new agent tools
NadavAvraham May 13, 2026
6cf4680
chore(agent-toolkit): regenerate dev graphql types for new agent oper…
NadavAvraham May 13, 2026
b924a9b
feat(agent-toolkit): add get_agent_catalog tool
NadavAvraham May 13, 2026
da245b0
fix(agent-toolkit): clean up get_agent_catalog variable assignment an…
NadavAvraham May 13, 2026
ca5cd0d
feat(agent-toolkit): add manage_agent_triggers tool
NadavAvraham May 13, 2026
9897389
test(agent-toolkit): add error propagation tests for add and remove t…
NadavAvraham May 13, 2026
45b5132
feat(agent-toolkit): add manage_agent_skills tool
NadavAvraham May 13, 2026
caec9a8
fix(agent-toolkit): improve manage_agent_skills control flow and add …
NadavAvraham May 13, 2026
8de165d
feat(agent-toolkit): add update_agent tool
NadavAvraham May 13, 2026
5deefcb
fix(agent-toolkit): improve update_agent null safety and test coverage
NadavAvraham May 13, 2026
836573b
feat(agent-toolkit): add manage_agent_state tool
NadavAvraham May 13, 2026
79a00f3
fix(agent-toolkit): improve manage_agent_state control flow, null saf…
NadavAvraham May 13, 2026
4d64cfc
feat(agent-toolkit): add manage_agent_knowledge tool
NadavAvraham May 13, 2026
30363fc
fix(agent-toolkit): fix update validation message and improve manage_…
NadavAvraham May 13, 2026
d23006e
fix(agent-toolkit): remove semicolons from tool descriptions to pass …
NadavAvraham May 13, 2026
551af0e
chore(agent-toolkit): bump version to 5.11.0
NadavAvraham May 13, 2026
4fd9a27
refactor(agent-toolkit): move returns inside try blocks and add skill…
NadavAvraham May 13, 2026
b798bbb
feat(agent-toolkit): add create_agent_skill tool
NadavAvraham May 13, 2026
ad43617
chore(agent-toolkit): bump version to 5.11.1
NadavAvraham May 13, 2026
57346f2
chore(agent-toolkit): revert version to 5.11.0
NadavAvraham May 13, 2026
d0dabc9
refactor(agent-toolkit): fold create_agent_skill into manage_agent_sk…
NadavAvraham May 13, 2026
560ea82
chore: remove design docs from branch (keep locally)
NadavAvraham May 13, 2026
5470cc8
fix(agent-toolkit): address PR review feedback on agent tools
NadavAvraham May 13, 2026
01b4755
fix(agent-toolkit): address PR #343 review feedback on agent tools
NadavAvraham May 14, 2026
68dffd0
refactor(agent-toolkit): split create_agent_skill out of manage_agent…
NadavAvraham May 14, 2026
5dd8870
chage tools split
NadavAvraham May 17, 2026
9622cdf
fix(agent-toolkit): address PR review feedback on agent tools
NadavAvraham May 17, 2026
0844441
review fixes
NadavAvraham May 26, 2026
fbb0485
chore(agent-toolkit): merge master into feat/agent-tools-expansion
NadavAvraham May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/agent-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mondaydotcomorg/agent-toolkit",
"version": "5.10.3",
"version": "5.11.0",
Comment thread
NadavAvraham marked this conversation as resolved.
Outdated


"description": "monday.com agent toolkit",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Two modes:

Do not mix prompt with manual profile fields in one request.

Created agents start in state INACTIVE and must be activated before they can be triggered. Instruct the user to activate from the monday.com agent settings UI.
Created agents start in state INACTIVE and must be activated before they can be triggered. After creation, call manage_agent_state with action:activate and the returned agent id.

created_at and updated_at are null in the response — call get_agent with the returned id afterward to fetch them.

Expand Down Expand Up @@ -137,7 +137,7 @@ USAGE EXAMPLES:

return {
content: {
message: `monday platform agent ${res.create_blank_agent.id} created in state INACTIVE — user must activate it from the monday.com UI before it can be triggered`,
message: `monday platform agent ${res.create_blank_agent.id} created in state INACTIVE — call manage_agent_state with action:activate and agent_id:${res.create_blank_agent.id} to activate it`,
agent: res.create_blank_agent,
},
};
Expand All @@ -163,12 +163,12 @@ USAGE EXAMPLES:
throw new Error('monday platform agent creation returned no id');
}

return {
content: {
message: `monday platform agent ${res.create_agent.id} created in state INACTIVE — user must activate it from the monday.com UI before it can be triggered`,
agent: res.create_agent,
},
};
return {
Comment thread
NadavAvraham marked this conversation as resolved.
Outdated
content: {
message: `monday platform agent ${res.create_agent.id} created in state INACTIVE — call manage_agent_state with action:activate and agent_id:${res.create_agent.id} to activate it`,
agent: res.create_agent,
},
};
} catch (error) {
rethrowWithContext(error, 'create monday platform agent');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { MondayAgentToolkit } from 'src/mcp/toolkit';
import { callToolByNameRawAsync, createMockApiClient, parseToolResult } from '../../test-utils/mock-api-client';
import { GetAgentTriggersCatalogQuery, GetAgentSkillsCatalogQuery } from 'src/monday-graphql/generated/graphql.dev/graphql';

describe('GetAgentCatalogTool', () => {
let mocks: ReturnType<typeof createMockApiClient>;

beforeEach(() => {
mocks = createMockApiClient();
jest.spyOn(MondayAgentToolkit.prototype as any, 'createApiClient').mockReturnValue(mocks.mockApiClient);
});

const mockTrigger = {
block_reference_id: 'status-change-ref',
name: 'Status Change',
description: 'Fires when a status column changes',
field_schemas: [{ field_key: 'board_id', value_schema: 'The ID of the board to watch' }],
required_fields: [{ field_key: 'board_id', depends_on: [], optional: false }],
};

const mockSkill = {
id: 'skill-1',
name: 'Board Manager',
description: 'Manages boards and items',
};

it('should return triggers catalog when type is triggers', async () => {
mocks.setResponseOnce({ agent_triggers_catalog: [mockTrigger] } as GetAgentTriggersCatalogQuery);

const result = await callToolByNameRawAsync('get_agent_catalog', { type: 'triggers' });
const parsed = parseToolResult(result);

expect(parsed.count).toBe(1);
expect(parsed.triggers[0].block_reference_id).toBe('status-change-ref');
});

it('should pass versionOverride dev when fetching triggers', async () => {
mocks.setResponseOnce({ agent_triggers_catalog: [] } as GetAgentTriggersCatalogQuery);

await callToolByNameRawAsync('get_agent_catalog', { type: 'triggers' });

expect(mocks.getMockRequest()).toHaveBeenCalledWith(
expect.stringContaining('getAgentTriggersCatalog'),
expect.objectContaining({ block_reference_ids: undefined }),
expect.objectContaining({ versionOverride: 'dev' }),
);
});

it('should pass block_reference_ids when provided', async () => {
mocks.setResponseOnce({ agent_triggers_catalog: [mockTrigger] } as GetAgentTriggersCatalogQuery);

await callToolByNameRawAsync('get_agent_catalog', { type: 'triggers', block_reference_ids: ['status-change-ref'] });

expect(mocks.getMockRequest()).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ block_reference_ids: ['status-change-ref'] }),
expect.anything(),
);
});

it('should return skills catalog when type is skills', async () => {
mocks.setResponseOnce({ agent_skills_catalog: [mockSkill] } as GetAgentSkillsCatalogQuery);

const result = await callToolByNameRawAsync('get_agent_catalog', { type: 'skills' });
const parsed = parseToolResult(result);

expect(parsed.count).toBe(1);
expect(parsed.skills[0].id).toBe('skill-1');
});

it('should pass versionOverride dev when fetching skills', async () => {
mocks.setResponseOnce({ agent_skills_catalog: [] } as GetAgentSkillsCatalogQuery);

await callToolByNameRawAsync('get_agent_catalog', { type: 'skills' });

expect(mocks.getMockRequest()).toHaveBeenCalledWith(
expect.stringContaining('getAgentSkillsCatalog'),
expect.anything(),
expect.objectContaining({ versionOverride: 'dev' }),
);
});

it('should return empty list with count 0 when no triggers exist', async () => {
mocks.setResponseOnce({ agent_triggers_catalog: [] } as GetAgentTriggersCatalogQuery);

const result = await callToolByNameRawAsync('get_agent_catalog', { type: 'triggers' });
const parsed = parseToolResult(result);

expect(parsed.count).toBe(0);
expect(parsed.triggers).toEqual([]);
});

it('should propagate errors when fetching triggers catalog', async () => {
mocks.setError('Unauthorized');

const result = await callToolByNameRawAsync('get_agent_catalog', { type: 'triggers' });

expect(result.content[0].text).toContain('Failed to fetch monday platform agent triggers catalog');
});

it('should propagate errors when fetching skills catalog', async () => {
mocks.setError('Unauthorized');

const result = await callToolByNameRawAsync('get_agent_catalog', { type: 'skills' });

expect(result.content[0].text).toContain('Failed to fetch monday platform agent skills catalog');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { z } from 'zod';
import {
GetAgentTriggersCatalogQuery,
GetAgentTriggersCatalogQueryVariables,
GetAgentSkillsCatalogQuery,
} from '../../../../../monday-graphql/generated/graphql.dev/graphql';
import { getAgentTriggersCatalogQuery, getAgentSkillsCatalogQuery } from './get-agent-catalog.graphql.dev';
import { ToolInputType, ToolOutputType, ToolType } from '../../../../tool';
import { BaseMondayApiTool, createMondayApiAnnotations } from '../../base-monday-api-tool';
import { rethrowWithContext } from '../../../../../utils';

export const getAgentCatalogToolSchema = {
type: z
.enum(['triggers', 'skills'])
.describe(
'Which catalog to fetch. "triggers" returns available trigger types with block_reference_id, field_schemas, and required_fields — use before calling manage_agent_triggers with action:add. "skills" returns available skills with id — use before calling manage_agent_skills.',
),
block_reference_ids: z
Comment thread
NadavAvraham marked this conversation as resolved.
Outdated
Comment thread
NadavAvraham marked this conversation as resolved.
Outdated
.array(z.string())
.optional()
.describe(
'Only applies when type is "triggers". Fetch specific entries by block_reference_id instead of the full catalog. Omit to return all trigger types.',
),
};

export class GetAgentCatalogTool extends BaseMondayApiTool<typeof getAgentCatalogToolSchema> {
name = 'get_agent_catalog';
type = ToolType.READ;
annotations = createMondayApiAnnotations({
title: 'Get monday Platform Agent Catalog',
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
});

getDescription(): string {
return `Fetch the account-wide catalog of available trigger types or skills for monday platform agents.

ALWAYS call this tool first before adding a trigger or skill to an agent:
- type:"triggers" — returns entries with block_reference_id (required for manage_agent_triggers action:add), name, description, field_schemas (describes the field_values shape to pass when adding — e.g. { board_id: "<ID>" }), and required_fields (fields the user must supply before you can call add).
- type:"skills" — returns entries with id (required for manage_agent_skills), name, description.

Never guess or invent a block_reference_id or skill id — always look them up here first.

USAGE EXAMPLES:
- List all trigger types: { "type": "triggers" }
- Fetch a specific trigger type: { "type": "triggers", "block_reference_ids": ["some-block-ref-id"] }
- List all skills: { "type": "skills" }`;
}

getInputSchema() {
return getAgentCatalogToolSchema;
}

protected async executeInternal(
input: ToolInputType<typeof getAgentCatalogToolSchema>,
): Promise<ToolOutputType<never>> {
if (input.type === 'triggers') {
try {
const variables: GetAgentTriggersCatalogQueryVariables = {
block_reference_ids: input.block_reference_ids,
};
const res = await this.mondayApi.request<GetAgentTriggersCatalogQuery>(
getAgentTriggersCatalogQuery,
variables,
{ versionOverride: 'dev' },
);
const catalog = res.agent_triggers_catalog ?? [];
return {
content: {
message:
'Available trigger types for monday platform agents. Use block_reference_id and inspect field_schemas/required_fields before calling manage_agent_triggers with action:add.',
count: catalog.length,
triggers: catalog,
},
};
} catch (error) {
rethrowWithContext(error, 'fetch monday platform agent triggers catalog');
}
}

try {
const res = await this.mondayApi.request<GetAgentSkillsCatalogQuery>(
getAgentSkillsCatalogQuery,
{},
{ versionOverride: 'dev' },
);
const catalog = res.agent_skills_catalog ?? [];
return {
content: {
message: 'Available skills for monday platform agents. Use id when calling manage_agent_skills.',
count: catalog.length,
skills: catalog,
},
};
} catch (error) {
rethrowWithContext(error, 'fetch monday platform agent skills catalog');
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { gql } from 'graphql-request';

export const getAgentTriggersCatalogQuery = gql`
query getAgentTriggersCatalog($block_reference_ids: [ID!]) {
agent_triggers_catalog(block_reference_ids: $block_reference_ids) {
block_reference_id
name
description
field_schemas {
field_key
value_schema
}
required_fields {
field_key
depends_on
optional
}
}
}
`;

export const getAgentSkillsCatalogQuery = gql`
query getAgentSkillsCatalog {
agent_skills_catalog {
id
name
description
}
}
`;
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export * from './get-agent/get-agent-tool';
export * from './create-agent/create-agent-tool';
export * from './delete-agent/delete-agent-tool';
export * from './get-agent-catalog/get-agent-catalog-tool';
export * from './manage-agent-triggers/manage-agent-triggers-tool';
export * from './manage-agent-skills/manage-agent-skills-tool';
export * from './update-agent/update-agent-tool';
export * from './manage-agent-state/manage-agent-state-tool';
export * from './manage-agent-knowledge/manage-agent-knowledge-tool';
Loading
Loading