feat: knowledge bases — list, plain text CRUD, and access probe#427
Conversation
Add get_ai_knowledge_bases, get_ai_knowledge_base_plain_text, create/update/delete_ai_knowledge_base_plain_text, and validate_knowledge_base_access with full SDK + MCP + CLI parity. All operations are pipe-scoped by pipe UUID (not the numeric id). Plain text limits are enforced client-side to fail fast: content 1-3500 and description 1-900 characters, both required (the backend rejects a blank description even though the GraphQL schema marks it optional). CLI gates writes on the read-access probe; MCP stays explicit-validate-first; deletes require confirmation. validate_ai_agent_behaviors gains optional data_source_ids: agent-level IDs are unioned with each behavior's dataSourceIds and checked against the pipe's knowledge bases, warning (never blocking) on unknown IDs and skipping the check with a single warning when the list cannot be read. Closes #412
adriannoes
left a comment
There was a problem hiding this comment.
Summary
Solid delivery of the #412 knowledge-base surface: SDK + MCP + CLI parity, probe semantics, docs/skills, and CI are in good shape (checkout + targeted tests green on tip). Two contract gaps should land before merge so agents and CLI scripts do not get false success or a self-referential discovery hint.
What worked well
- Thin shells over
PipefyClient, staticgql()queries, and the shared GraphQL problem classifier. - Client-side content/description limits and required description called out at point of use.
- Probe documents read-only entitlement; CLI create/update gate and MCP explicit-validate-first match the docs.
Also noted
- create/update still report success when
_unwrap_plain_textyields{}(no GraphQL errors but null nested payload).getin the same module rejects empty, andcreate_ai_agentraises on a missing nested payload. Worth the same empty-payload guard (or an SDKValueError) when convenient; fine as a follow-up if the two inline threads land first.
Review path
- Checked out
aa21c95, ran ruff on touched KB paths and 55 targeted SDK/MCP/CLI/preflight tests; GitHub CI green on tip. - Adversarial passes and refutation kept the CLI empty-get parity gap and the list-tool self-referential
not_foundhint; create/update empty unwrap stayed as a non-blocking note.
…pty-write guard The CLI `kb plain-text get` now mirrors the MCP tool's not-found handling: an empty SDK result returns success=false and exits 1 instead of reporting success. The MCP not-found discovery hint is scoped to per-id tools; the list tool's own failure no longer tells the caller to retry the call that just failed. A write mutation returning no errors but a null nested payload now raises in the SDK instead of unwrapping to an empty success, so create/update can never report success for a write that may not have persisted.
|
@adriannoes All three review points landed in 98c3a8d — the two inline threads plus the non-blocking empty-unwrap note: |
adriannoes
left a comment
There was a problem hiding this comment.
Summary
Rechecked tip 98c3a8d. The follow-up commit addresses the review notes: CLI empty-get now fails closed with exit 1, the list-tool discovery hint is no longer self-referential, and write unwraps raise when the nested plain-text payload is missing. Targeted KB tests and CI are green on tip.
Thanks for addressing those points cleanly, including the regression coverage.
Review path
- Compared the fix commit against the earlier REQUEST_CHANGES threads.
- Re-ran the KB SDK/MCP/CLI unit suite locally (48 passed); GitHub checks green on tip.
Closes #412. Third phase of the AI Agents milestone (knowledge bases, capabilities & model selection); builds on the provider-discovery SDK error classifier from #411.
What ships
New pipe-scoped knowledge base surface with full SDK + MCP + CLI parity:
get_ai_knowledge_basespipefy kb listget_ai_knowledge_base_plain_textpipefy kb plain-text getcreate_ai_knowledge_base_plain_textpipefy kb plain-text createupdate_ai_knowledge_base_plain_textpipefy kb plain-text updatedelete_ai_knowledge_base_plain_textpipefy kb plain-text deletevalidate_knowledge_base_accesspipefy kb validate-accessvalidate_ai_agent_behaviors/pipefy agent validate-behaviorsgain an optionaldata_source_ids(--data-source-id, repeatable): agent-level IDs are unioned with each behavior'sdataSourceIdsand checked against the pipe's knowledge bases. Unknown IDs are warnings only (validstays true); a failed list probe skips the check with a single warning.Contract (validated against the live schema, Core master resolvers, and the downstream data-source model)
pipeUuid), never the numeric id.plain_text_id/ knowledge baseidare data-source UUIDs from the list.input:wrapper. Auth: reads requireread_ai_agents; writes requiremanage_ai_agents. A green probe proves read access only, never write entitlement.content1-3500 anddescription1-900 characters.descriptionis required on create — the GraphQL schema marks it optional, but the backend rejects a blank one, so the toolkit requires it and surfaces that as a clear client-side error rather than a 422.Behavior boundaries
confirm=true; CLI--yesor prompt).Docs & skills
docs/parity.md(6 rows + counts),README.md(168 tools, new Knowledge bases domain),docs/mcp/tools/knowledge-bases.md,docs/mcp/README.mdindex, and thepipefy-ai-agentsskill (validate-access → create plain text → attach viadataSourceIdsflow). Skill-ref allowlist gainskb.Testing
uv run pytest -m "not integration"(3573 passed,PIPEFY_*unset) + ruff check/format + import-linter + skill-ref linter +bump_version.py verify+ parity row-count (168) + remote-seed drift guard green./simplify+/code-reviewrun and findings applied. Exercised end-to-end against dev pipe303088927through the MCP server running this branch's code:validate_knowledge_base_accessok: true,knowledge_base_count: 3, note states read access only (read_ai_agents), nevermanage_ai_agentsget_ai_knowledge_basesid/typefordataSourceIdsid/type/name/description/updatedAtcreate_ai_knowledge_base_plain_text54208963-…, all fields echoedget_ai_knowledge_base_plain_textupdate_ai_knowledge_base_plain_text(content only)validate_ai_agent_behaviorswithdata_source_ids(real + bogus)validunaffected by membershipvalidset only by an unrelated field problemconfirm=false)requires_confirmation: true, mutation not runconfirm=true)deleted_idreturned, absent from the follow-up listdescriptionINVALID_ARGUMENTS,path: ["description"], "Field required"get_ai_knowledge_base_plain_text(bogus id)kind: not_found,AI_CHAT_REQUEST_FAILED, "Use 'get_ai_knowledge_bases'…" appended,correlation_idcarriedvalidate_knowledge_base_access(bogus pipe uuid)RESOURCE_NOT_FOUND,kind: not_found,correlation_idcarriedValueError"content must be at most 3500 characters (got 3501)"; 3500 reaches the wire (proven in-process + unit-tested)Rows 9–13 are the client-side and classified-error acceptance criteria exercised live; row 6 is the
data_source_idsmembership criterion (unknown IDs warn, never block).