Skip to content

feat(agent-toolkit): agents subgraph tools expansion#343

Open
NadavAvraham wants to merge 28 commits into
masterfrom
feat/agent-tools-expansion
Open

feat(agent-toolkit): agents subgraph tools expansion#343
NadavAvraham wants to merge 28 commits into
masterfrom
feat/agent-tools-expansion

Conversation

@NadavAvraham
Copy link
Copy Markdown
Collaborator

monday item

https://monday.monday.com/boards/10045819454/pulses/10045820228

Summary

  • Adds 6 new tools to @mondaydotcomorg/agent-toolkit covering the full agents subgraph surface
  • get_agent_catalog — discovers available trigger types and skills account-wide (READ)
  • manage_agent_triggers — list, add, and remove triggers on an agent (WRITE)
  • manage_agent_skills — create custom skills, attach and detach skills from an agent (WRITE)
  • update_agent — update an agent's name, role, description, or execution plan (WRITE)
  • manage_agent_state — activate, deactivate, or manually run an agent (WRITE)
  • manage_agent_knowledge — list, grant, update, and revoke an agent's access to boards and docs (WRITE)
  • Bumps package version to 5.11.0

Design decisions

  • Tool descriptions encode catalog-first workflows so agents know to call get_agent_catalog before adding triggers or skills
  • manage_agent_triggers and manage_agent_knowledge include a list action to support the lookup-before-mutate pattern (get node_id / inspect current state before remove/update)
  • All tools use versionOverride: 'dev' — the agents subgraph is still on the dev API version
  • manage_agent_skills consolidates skill creation (create_agent_skill mutation) alongside attach/detach in one tool since they're all skill management operations
  • GraphQL operations are co-located with each tool's directory rather than centralised in shared/

Test plan

  • npm test passes (1013 tests across 55 suites)
  • npm run build compiles cleanly
  • Each tool has happy-path, validation-error, null-response, and API-error-propagation coverage

🤖 Generated with Claude Code

NadavAvraham and others added 26 commits May 13, 2026 17:30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the get_agent_catalog READ tool that fetches the account-wide catalog of available trigger types or skills for monday platform agents via the dev API version.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d test assertion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements list/add/remove actions for agent triggers, using the dev API versionOverride. All 10 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rigger actions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the manage_agent_skills tool supporting add/remove actions, with full test coverage for happy paths, request shape verification, and error propagation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…null response tests

Use explicit if/else branching in executeInternal and add tests verifying the ?? false fallback when the API returns null for add_skill_to_agent or remove_skill_from_agent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the update_agent WRITE tool that patches an existing monday platform agent's profile or execution plan, including only the provided fields in the mutation input.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Throw explicit error when update_agent returns no data instead of falling back to {}
- Strengthen agent_model describe string to match create_agent's STRONGLY DISCOURAGED wording
- Add profile.name assertion to happy-path test to confirm response forwarding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds manage_agent_state tool supporting activate, deactivate, and run actions for monday platform agents. Includes 11 unit tests covering happy paths, error propagation, versionOverride, default inactive_reason, and null fallbacks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ety, and test coverage

Restructure try/catch blocks so return statements are outside the try, add explicit null check for run_agent response, and add test coverage for null run_agent case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements list/add/update/remove actions for managing a monday platform
agent's access to boards and docs, following the restructured try/catch
pattern from manage-agent-state-tool.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…agent_knowledge test coverage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…safety checks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s list note

Move return statements inside try blocks (using const) for all branches in manage-agent-state-tool.ts and manage-agent-knowledge-tool.ts, eliminating non-null assertions. Add a note to manage_agent_skills description that there is no list action because the platform does not yet expose that query.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ills tool

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- create_agent: guide calling manage_agent_state(activate) after creation instead of redirecting to the monday.com UI
- manage_agent_state: narrow inactive_reason to DEACTIVATED_BY_USER only (remove internal ACCOUNT_LEVEL_BLOCKING); describe when to pass it vs omit
- manage_agent_knowledge: document that files in the list response cannot be managed via this tool and redirect to the platform UI
- manage_agent_skills: clarify create→add flow — use the id returned by action:create directly, no catalog lookup needed
- update-agent-tool.test: add missing null-response test for update_agent returning no data
- manage-agent-state-tool.test: update test to reflect removed ACCOUNT_LEVEL_BLOCKING enum value

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@RanEldann RanEldann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strong addition overall — the 6 new tools follow established patterns in the toolkit, tests cover happy paths plus most error/null/validation cases, and the GraphQL operations are correctly wired. Auth model is fine: JWT-scoped, every mutation goes through authorizeAgentAction('edit', agentId), no security concerns from the toolkit perspective.

Three blocking issues

  1. Prettier will fail CIcreate-agent-tool.ts:166-171 has an 8-space indent in a 6-space block. Looks like an editor mishap during the latest edits.
  2. .optional() + manual throw instead of z.discriminatedUnion across all four manage_* tools. The repo already uses discriminated unions in 4 places (update-doc-tool.schema.ts, create-doc-tool.ts). The current pattern means LLMs see all action-conditional fields as optional in the JSON schema and only learn requirements via runtime errors.
  3. field_values: z.record(z.unknown()) in manage_agent_triggers provides no schema guidance to the LLM. The description tells it to call get_agent_catalog and follow field_schemas, but the JSON schema is fully untyped — three different shape conventions hide behind one record.

Theme: description ↔ code drift

Several tool descriptions claim or imply behaviors the code doesn't deliver:

  • inactive_reason's "omit if ambiguous" is meaningless because the code defaults to the same value either way (it's also a 1-value enum, so the field is pure noise)
  • update_agent's "profile or execution plan" overpromises — avatar_url, background_color, goal, user_prompt aren't in UpdateAgentInput
  • agent_model's "degrades the agent's performance" is wrong — invalid values are rejected by the server, not degraded
  • manage_agent_triggers doesn't mention that the catalog excludes 3rd-party (OAuth) triggers — LLMs will look up Slack/Salesforce and be confused they're missing
  • manage_agent_knowledge's "call list first" is overstated — only needed for update/remove, not add

Theme: cross-tool inconsistency

  • update_agent returns { content: agent } while siblings return { content: { message, agent } } — LLM has to learn per-tool shapes
  • agent_id (new tools) vs id (existing update/get/delete-agent) — same concept, two names
  • count field on most list responses but missing from knowledge list

Nits

  • Missing CHANGELOG.md entry for 5.11.0 (the agent-toolkit/CLAUDE.md mandates this — though to be fair, CHANGELOG was already stale at 5.7.1)
  • update-agent-tool.test.ts has 3 expect()s in a single it() — violates the "one assert per test" rule used elsewhere
  • rethrowWithContext strings are verbose and inconsistent — 4 of them have double-"agent" ("list agent knowledge for monday platform agent", etc.). The "monday platform agent" suffix is wasted tokens in every error
  • Domain validation errors (e.g. throw new Error('create_agent_skill returned no data')) get double-wrapped to "Failed to X: <inner>" because the throw is inside the try block
  • trigger_uuid returned by manage_agent_state action:run has no companion query yet — the description should say "store for future correlation; no run-status query exists yet"
  • manage_agent_knowledge list returns a files array the tool can't act on; the description has to apologize. Either drop from the GraphQL selection or split into a separate read tool

Recommendations

  1. Fix Prettier first (item 1) — that's CI.
  2. Convert the four manage_* schemas to z.discriminatedUnion('action', [...]). This single change fixes findings 2, 4, 8, 13, plus removes the manual cross-field throws.
  3. Fix the description honesty issues (medium-severity but cheap) — they directly affect tool-call success rate in production.
  4. Align update_agent's return shape and rename idagent_id for consistency.
  5. Optional but recommended: type agent_model as z.nativeEnum(AgentModel) so wrong values fail at zod time with a clear list of valid options, instead of producing a confusing GraphQL error.

Nice work overall — happy to clarify or drop any of the smaller items.

Comment thread packages/agent-toolkit/package.json
NadavAvraham and others added 2 commits May 14, 2026 13:16
- Fix Prettier indent in create-agent-tool.ts (CI blocker)
- update_agent: rename id→agent_id for consistency with new tools,
  use z.nativeEnum(AgentModel), fix description to list only updatable
  fields, add empty-input guard, fix return shape to { message, agent }
- manage_agent_state: remove inactive_reason (1-value enum always
  defaulted), hardcode DeactivatedByUser, clarify trigger_uuid has no
  companion run-status query
- manage_agent_knowledge: scope "call list first" to update/remove,
  add count field to list response
- manage_agent_triggers: narrow field_values to typed union, add OAuth
  exclusion note, clarify add returns no node_id
- get_agent_catalog: add .min(1) to block_reference_ids
- Update tests: split 3-expect test, agent_id naming, new return shape,
  simplified inactive_reason coverage
- Add CHANGELOG.md entry for 5.11.0

Co-authored-by: Cursor <cursoragent@cursor.com>
…_skills

create_agent_skill (account-catalog CRUD) and manage_agent_skills
(attach/detach on a specific agent) operate on different domain
entities, so they now live in separate tools. manage_agent_skills
action enum shrinks to [add, remove]; all create logic and the
createAgentSkill GraphQL mutation move to the new create_agent_skill
tool.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@RanEldann RanEldann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nadav 👑 you're a king. Genuinely impressive turnaround — almost every finding addressed, several solved structurally (extracting create_agent_skill, dropping inactive_reason entirely), and descriptions are now honest about what each tool actually does. This is a major enhancement — agents can now manage the full agent lifecycle end-to-end with schemas they can actually act on. Approving 🎉

One thought on the discriminated-union pushback before we move on — I think the blocker is smaller than it looked, and the LLM ergonomics win is real:

The actual constraint is just Input extends ZodRawShape in BaseMondayApiTool plus 3–4 z.object(inputSchema) sites in toolkit.ts. ~15 lines, fully backwards-compatible:

// base-monday-api-tool.ts
export type ToolInputSchema = ZodRawShape | ZodTypeAny | undefined;

export abstract class BaseMondayApiTool<
  Input extends ToolInputSchema,
  Output extends Record<string, unknown> = never,
>
// toolkit.ts — small helper
function buildZodSchema(input: any): ZodTypeAny | undefined {
  if (!input) return undefined;
  if (typeof input.safeParse === 'function') return input;  // already a Zod schema
  return z.object(input);  // ZodRawShape — existing tools
}
// then replace the 4 z.object(inputSchema) sites with buildZodSchema(inputSchema)

Then each manage_* schema becomes z.discriminatedUnion('action', [...]) with one z.object per variant. zodToJsonSchema produces oneOf with per-action required arrays — the LLM sees "for action=add, resource_id + scope_type + permission_type are required" in the schema itself instead of parsing it out of prose.

LLMs miss conditional prose ("Required for action:X") reasonably often. Discriminated oneOf cuts misuse-on-first-try meaningfully on real workloads. Bonus: drops the manual if (!input.x) throw blocks and TypeScript narrows the input type per case branch in executeInternal.

Fully backwards-compatible — every existing ZodRawShape tool keeps working unchanged. Not blocking, just smaller than the "follow-up" reply implied. Up to you whether to do it here or a separate PR 🙂

Great work 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants