Skip to content

feat: add lyzr-tools plugin bridging Lyzr-authorized tools into GitAgent - #78

Open
akshatkumar2808 wants to merge 2 commits into
open-gitagent:mainfrom
akshatkumar2808:feat/lyzr-tools-bridge
Open

feat: add lyzr-tools plugin bridging Lyzr-authorized tools into GitAgent#78
akshatkumar2808 wants to merge 2 commits into
open-gitagent:mainfrom
akshatkumar2808:feat/lyzr-tools-bridge

Conversation

@akshatkumar2808

Copy link
Copy Markdown

Summary

  • Adds a lyzr-tools plugin that discovers Lyzr-authorized tools (Gmail, Slack, MCP servers) and proxies execution through Lyzr instead of requiring separate local credentials
  • Registers discovered tools as lyzr_-prefixed GitAgent tools; unauthorized tools return a structured authorization_required result instead of prompting for local credentials
  • Redacts secrets from tool result details; adds prompt guidance preferring lyzr_* tools over local duplicate skills
  • Enabled by default in agent.yaml; no-ops with a warning if LYZR_API_KEY isn't set (no network call without a key)

See docs/lyzr-tool-auth-rca.md for the RCA/design and docs/lyzr-tool-bridge-test-cases.md for the acceptance criteria this targets.

Test plan

  • npm run build && npm test — 59/59 passing (32 new in test/lyzr-tools.test.ts, no real network calls)
  • Verified end-to-end through the real plugin loader (not just mocks): no-API-key no-op path, and full discovery→register→execute cycle against a local HTTP stub

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 shreyas-lyzr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment thread plugins/lyzr-tools/lib/discover.ts Outdated
Comment thread plugins/lyzr-tools/lib/discover.ts Outdated
return [];
}

function normalizeInputSchema(schema: unknown): { properties: Record<string, any>; required?: string[] } {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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:

Suggested change
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: {} };
}

Comment thread plugins/lyzr-tools/lib/redact.ts Outdated
Comment thread agent.yaml
…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>
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.

2 participants