feat: add lyzr-tools plugin bridging Lyzr-authorized tools into GitAgent - #78
feat: add lyzr-tools plugin bridging Lyzr-authorized tools into GitAgent#78akshatkumar2808 wants to merge 2 commits into
Conversation
GitAgent's LYZR_API_KEY was only wired into the model path, so users with Gmail/Slack/etc. already authorized in Lyzr still had to configure separate local credentials (e.g. local Gmail SMTP app passwords) for tool execution. Adds a lyzr-tools plugin that: - Discovers authorized provider actions (GET /v3/providers/tools/actions/*) and MCP server tools (/v3/tools/mcp/servers*), cross-referenced against connected-account status (/v3/tools/credentials/connected_accounts). - Registers each as a lyzr_-prefixed gitagent tool, avoiding collisions with local skills by construction. - Proxies execution through /v3/inference/tools/execute or /v3/tools/mcp/tools/execute, normalizing results into success / authorization_required / error, with secret redaction on all details. - Adds prompt guidance preferring lyzr_ tools over local duplicates (e.g. the bundled gmail-email skill) when both exist. Enabled by default in agent.yaml; no-ops with a single warning if LYZR_API_KEY isn't set, so it never makes a network call without a key. See docs/lyzr-tool-auth-rca.md for the RCA and design this implements, and docs/lyzr-tool-bridge-test-cases.md for the acceptance criteria covered by test/lyzr-tools.test.ts (32 tests, no real network calls). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
shreyas-lyzr
left a comment
There was a problem hiding this comment.
Four issues worth addressing before merge — one is a confirmed functional break on the default config, one is a silent misconfiguration that yields a broken user experience with no log output to help diagnose it, one is a schema normalization gap that silently drops valid tool parameters, and one is a key-based redaction limitation that can let raw credential strings through to model context. Inline comments below.
| return []; | ||
| } | ||
|
|
||
| function normalizeInputSchema(schema: unknown): { properties: Record<string, any>; required?: string[] } { |
There was a problem hiding this comment.
normalizeInputSchema only passes through schemas that are plain objects with a properties key. If Lyzr returns an action schema in OpenAI function-calling style — where parameters is an array of { name, type, description } objects, which is a common ACI format — that array fails the "properties" in schema check and is silently replaced with { properties: {} }.
The tool registers with no known parameters; the model has to guess argument names, which causes silent failures for any required fields.
At minimum, handle the array case by converting it to a JSON Schema object shape:
| function normalizeInputSchema(schema: unknown): { properties: Record<string, any>; required?: string[] } { | |
| function normalizeInputSchema(schema: unknown): { properties: Record<string, any>; required?: string[] } { | |
| if (Array.isArray(schema)) { | |
| // OpenAI/ACI-style: [{name, type, description, required?}] | |
| const properties: Record<string, any> = {}; | |
| const required: string[] = []; | |
| for (const p of schema as Array<Record<string, any>>) { | |
| if (!p.name) continue; | |
| properties[p.name] = { type: p.type ?? "string", description: p.description ?? "" }; | |
| if (p.required) required.push(p.name); | |
| } | |
| return required.length ? { properties, required } : { properties }; | |
| } | |
| if (schema && typeof schema === "object" && "properties" in (schema as Record<string, unknown>)) { | |
| return schema as { properties: Record<string, any>; required?: string[] }; | |
| } | |
| return { properties: {} }; | |
| } |
…n hardening
- Discover tools from the agent's own tool_configs (GET /v3/agents/{id})
instead of per-provider listProviderActions calls: a real agent's
tool_configs already carry human-named connected integrations
(tool_name, tool_source, action_names, provider_uuid, credential_id),
which is confirmed correct against a live account. This sidesteps the
missing tool_source query param that made the old path 400 on the
default gmail,slack config.
- Warn when user_id is unset instead of silently marking every tool
unauthorized with no diagnostic trail.
- Normalize OpenAI/ACI-style array input schemas instead of dropping
them to an empty {properties: {}}.
- Redact token-shaped strings by pattern, not just by key name, so a
raw OAuth token returned under an innocuous key (e.g. `result`)
still gets masked; document the residual risk in README.
- Add rendered HTML copies of the RCA and test-case docs.
- agent.yaml: add missing trailing newline.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
lyzr-toolsplugin that discovers Lyzr-authorized tools (Gmail, Slack, MCP servers) and proxies execution through Lyzr instead of requiring separate local credentialslyzr_-prefixed GitAgent tools; unauthorized tools return a structuredauthorization_requiredresult instead of prompting for local credentialsdetails; adds prompt guidance preferringlyzr_*tools over local duplicate skillsagent.yaml; no-ops with a warning ifLYZR_API_KEYisn't set (no network call without a key)See
docs/lyzr-tool-auth-rca.mdfor the RCA/design anddocs/lyzr-tool-bridge-test-cases.mdfor the acceptance criteria this targets.Test plan
npm run build && npm test— 59/59 passing (32 new intest/lyzr-tools.test.ts, no real network calls)