Knowledge base data lookups: typed conditions and full-replacement updates#433
Conversation
…ment updates Adds the fifth phase of the knowledge base milestone: pipe-scoped data lookup sources across SDK, MCP, and CLI. A data lookup lets an AI agent search cards in a source pipe by conditions and return selected field values. Tools (MCP ↔ CLI): get/create/update/delete_ai_knowledge_base_data_lookup ↔ pipefy kb data-lookup get/create/update/delete. Contract enforced client-side (the backend under-validates in ways that only surface when an agent later runs the lookup): source_repo_id must be the numeric pipe ID; output_fields is 1-30 field IDs; every condition is typed (static needs a string value, AI-filled needs inputName/inputType/inputDescription and no value). Reads never return conditions, so updates require the full definition on every call and docs tell callers to keep the definition as the client-side source of truth. Writes require manage_ai_agents; the CLI gates on the read probe; deletes require confirmation. Consolidates the shared knowledge base description cap and the write-unwrap / delete-result / delete-failure helpers now that a third kind exists.
rich colorizes the option name in Typer's error box, splitting it with ANSI codes; the exact '--conditions'/'--output-fields' prefix is only stable when color is off (local), so CI failed on the substring match.
adriannoes
left a comment
There was a problem hiding this comment.
Summary
Solid fifth KB phase: full SDK/MCP/CLI parity for data lookups, typed conditions, full-replacement updates, and confirm-delete, with green CI and a green local unit suite (checkout+tests). Not a merge blocker on behavior; one docs count mismatch would be good to fix before merge (Knowledge bases domain row still at 10 while this PR lands four data-lookup tools and the headline says 176).
What worked well
- Full surface lockstep (registry 176, parity, skills create-attach-full-replacement flow, CLI help golden).
- Client-side contract matching real backend under-validation (numeric
source_repo_id, static vs AI-filled conditions,output_fields1-30), documented at the point of use. - Deliberate, explained divergences from #414 rather than silent mismatch.
Also noted
- Prefer an ASCII digit check for
source_repo_id(same spirit asPIPEFY_ORG_ID/^[0-9]+$) overstr.isdecimal(), which accepts Unicode Nd digits. Not a proven production break; consistency and test coverage if you touch that path. - Document the list type discriminator
data_lookupsonget_ai_knowledge_bases(tool docstring, knowledge-bases.md, skill). It is asymmetric vsknowledge_base_plain_texts/knowledge_base_documents. - AI-filled missing-field errors use snake_case (
input_name, …) while public docs teach camelCase (inputName, …). Worth aligning on the next edit of that path.
Review path
- Checked out the PR tip, ran package unit tests and ruff; CI green on tip.
- Subagent passes covered security, architecture, tests, agent UX, and bug hunt; README domain count (10 vs 14 / table sum 172 vs 176) survived refutation as the only inline item.
- Bugbot UUID read-then-update trap was adjusted: create shares the numeric guard; intentional hardening, not a ship blocker.
…oc polish - Bump the Knowledge bases domain-table row to 14 (data lookups) so the per-domain counts sum to the 176 headline; mention data lookups in the blurb. - Guard source_repo_id with an ASCII-digit check (isascii() and isdigit()) instead of isdecimal(), which accepts non-ASCII Unicode digits. - Name the AI-filled condition fields in camelCase (inputName/inputType/ inputDescription) in validation errors, matching the tool/docs vocabulary. - Document the asymmetric data_lookups list discriminator on get_ai_knowledge_bases (tool docstring, knowledge-bases.md, skill).
|
Thanks for the thorough pass, @adriannoes — all four points addressed in 0f3c005 (CI green):
On the disclosure note from the testing matrix (upstream Core returns a raw internal error hash that the classifier passes through verbatim on rejection paths): it is pre-existing and shared with the plain-text/document phases, and it is already tracked in the internal bug tracking (1415676177), so I've left it out of scope here. |
adriannoes
left a comment
There was a problem hiding this comment.
Summary
Approving on tip 0f3c005. The follow-up commit addresses the review notes: Knowledge bases domain count is 14 (table sums to 176), source_repo_id uses an ASCII digit guard, AI-filled validation errors use camelCase aliases, and data_lookups is documented on the list surface. CI is green on tip.
What worked well
- Fast, complete response to the review comments in one focused commit.
- The original data-lookup surface (parity, typed conditions, full-replacement updates, confirm-delete) remains solid.
Thanks for the clean follow-up, @mocha06.
Review path
- Re-checked tip after the review-address commit; verified README domain arithmetic, ASCII
source_repo_idguard, camelCase error wording, anddata_lookupsdocs. - CI lint/test/skill frontmatter green on tip.
Motivation
Fifth phase of the knowledge base milestone (#414): give the SDK, MCP server, and CLI full coverage for pipe-scoped data lookups — the third knowledge base source kind, after plain text (#427) and documents (#428). A data lookup lets an AI agent search cards in a source pipe by conditions and return selected field values, attached to an agent or behavior via
dataSourceIds.What ships
Full SDK → service → client → MCP → CLI → docs → skills → tests, in one PR (one phase = one PR).
get_ai_knowledge_base_data_lookuppipefy kb data-lookup getcreate_ai_knowledge_base_data_lookuppipefy kb data-lookup createupdate_ai_knowledge_base_data_lookuppipefy kb data-lookup updatedelete_ai_knowledge_base_data_lookuppipefy kb data-lookup deleteRegistry moves 172 → 176 tools; parity.md, README counts, the knowledge-bases doc page, the AI-agents skill, and the CLI help golden are updated in lockstep.
Proven contract (traced to the owning layer, not just the schema)
Every argument was walked through the full delegation chain (Core GraphQL → the AI chat service's JSON:API → the
DataSourcemodel → the agent runtime), not inferred from the schema.read_ai_agents; all writes needmanage_ai_agents(same milestone invariant as phases 3/4).pipe_uuid: the pipe UUID.data_lookup_id: the data-source UUID (from the list).source_repo_id: the numeric pipe ID. The schema types itIDand create-time authorization would accept a UUID, but the agent runtime integer-coerces the stored value — a UUID persists successfully and then breaks the lookup at run time. Enforced client-side as decimal-digits-only.name: required.description: required, 1-900 chars — schema-optional but the backingDataSourcemodel rejects a blank one (the shared knowledge base rule).output_fields: required, 1-30 entries (backend model cap), each a non-blank field ID (field slugs plus static fields likeid,title,created_at).conditions: required, non-empty. Each needsfield+operator(an opaque backend string, e.g."eq","contains") and is one of two shapes:valuerequired, must be a non-blank string. The write path validates onlyfield/operator; a missing or non-string value is accepted by the API and then breaks the lookup at agent run time, so it is enforced client-side.usingFillWithAi: truewithinputName,inputType,inputDescription(backend-validated);valuemust be omitted (the runtime supplies it, so a static value would be silently ignored).attribute/fieldUuid(schema-supported, backend-specific search modes) are accepted so externally-created lookups round-trip; unknown keys are rejected.Behavior boundaries
conditions— the API stores them but Core's type does not expose them, so callers keep their definition as the client-side source of truth.source_repo_id,output_fields, andconditionsare required on every update (the complete set, not a delta) and an omittedsearch_queryis cleared. Onlyname/descriptionare partial.search_queryis optional everywhere; it is a backend-defined search-mode marker, not free text — callers leave it unset unless they know the backend value they need.confirm=true; CLI--yesor prompt). CLI writes gate on the read-access probe first.Divergences from the issue text
source_repo_idis validated as numeric, not treated as "opaque, no format coercion" — a UUID passes create-time authorization but breaks the lookup at agent run time (see contract above).search_queryis optional on update, not required as the issue listed — it is optional at every layer, and requiring it would make lookups without one un-updatable; omission clears it (documented at all three surfaces).Docs & skills touched
docs/parity.md,docs/mcp/README.md,docs/mcp/tools/knowledge-bases.md(new data-lookup section),README.md(tool count),skills/ai-agents/pipefy-ai-agents/SKILL.md(create-with-AI-filled-condition → attach → full-replacement-update flow).Testing
Offline gates: full suite (3669 passed),
ruff check+format --check,lint-imports,bump_version.py verify, skill-ref + frontmatter linters, parity/remote-seed drift guards, CLI help golden, packaging wheel build. 132 knowledge base tests across SDK/MCP/CLI, including condition typing rules, full-definition update enforcement, confirm-delete, and the client-side limit/format checks (proven in-process rather than through pathological live inputs).Live end-to-end against pipe
303088927(dev):ok: true, count 4, read-only notetype: data_lookupsconfirmrequires_confirmation: trueconfirm=truedeleted_idreturnedkind: not_found, hint, correlation idkind: not_found, correlation idValueErrorbefore any network call