Skip to content

feat: Include available connectors in search/execute tool descriptions#355

Merged
shashi-stackone merged 8 commits intomainfrom
feat/dynamic-connector-descriptions
Apr 7, 2026
Merged

feat: Include available connectors in search/execute tool descriptions#355
shashi-stackone merged 8 commits intomainfrom
feat/dynamic-connector-descriptions

Conversation

@shashi-stackone
Copy link
Copy Markdown
Contributor

@shashi-stackone shashi-stackone commented Apr 2, 2026

Summary

  • openai({ mode: 'search_and_execute' }) now discovers available connectors
    and injects them into the tool_search and tool_execute descriptions
  • LLM sees which connectors are available before calling search, improving
    trigger reliability
  • No breaking changes — getTools() signature unchanged

A recurring issue with Search/Execute is that search doesn't reliably trigger
in the first place — the LLM doesn't know what's searchable. By dynamically
listing connector keys in the tool description (e.g. "Available connectors:
bamboohr, calendly, jotform"), the LLM has the context it needs to trigger
search confidently.

New things

  • Add configurable HTTP timeout for tool execution (default 60s, was httpx's 5s default)
  • Timeout can be set top-level StackOneToolSet(timeout=120) or in execute config execute={"timeout": 120}
  • Fix account_ids propagation from execute config to internal tools (fixes add utilities test #167)
  • Inject available connector names into tool_search/tool_execute descriptions for better LLM accuracy
  • Add Workday integration example demonstrating timeout and account scoping

Resolves:
StackOneHQ/stackone-ai-python#166
#355

Connector discovery is best-effort : if it fails, descriptions remain generic.

@shashi-stackone shashi-stackone requested a review from a team as a code owner April 2, 2026 13:10
Copilot AI review requested due to automatic review settings April 2, 2026 13:10
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 2, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@stackone/ai@355

commit: 84a6993

@shashi-stackone shashi-stackone changed the title Include available connectors in search/execute tool descriptions [WIP] Include available connectors in search/execute tool descriptions Apr 2, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Requires human review: This is a breaking change that converts the getTools method signature from synchronous to asynchronous and is also marked as a work-in-progress (WIP).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the agent “search and execute” meta-tools by dynamically including the set of available connector keys in the tool_search / tool_execute descriptions, so the LLM can see what’s searchable before deciding to call them.

Changes:

  • Extend createSearchTool / createExecuteTool to optionally append an “Available connectors: …” suffix to their descriptions.
  • Make StackOneToolSet.buildTools() (and getTools()) async to best-effort fetchTools() and derive connector keys via Tools.getConnectors().
  • Update openai({ mode: 'search_and_execute' }) to await the async tool builder.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

src/toolsets.ts Outdated
Comment on lines 645 to 647
async getTools(options?: { accountIds?: string[] }): Promise<Tools> {
return this.buildTools(options?.accountIds);
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

getTools() now returns a Promise<Tools> instead of Tools, which is a breaking API change for consumers (and the JSDoc still describes a synchronous Tools return). Consider preserving the existing sync method (e.g., keep getTools() sync with generic descriptions and add a new async variant like getToolsAsync()/getTools({ includeConnectorsInDescription: true })), or clearly treat this as a major-version change and update the JSDoc @returns accordingly.

Copilot uses AI. Check for mistakes.
src/toolsets.ts Outdated
Comment on lines +659 to +669
// Discover available connectors for dynamic descriptions
let connectors = '';
try {
const allTools = await this.fetchTools({ accountIds });
const connectorSet = allTools.getConnectors();
if (connectorSet.size > 0) {
connectors = Array.from(connectorSet).sort().join(', ');
}
} catch {
// Best-effort: if discovery fails, use generic descriptions
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

buildTools() now calls fetchTools() up front just to compute connector names. This adds an extra network/IO round trip whenever openai({ mode: 'search_and_execute' }) (or getTools()) is used, and tool_execute will then call fetchTools() again on first execution because its cache starts empty. Consider reusing the prefetched allTools to seed tool_execute’s cache (or passing prefetched tools into createExecuteTool) to avoid duplicate fetches and reduce startup latency.

Suggested change
// Discover available connectors for dynamic descriptions
let connectors = '';
try {
const allTools = await this.fetchTools({ accountIds });
const connectorSet = allTools.getConnectors();
if (connectorSet.size > 0) {
connectors = Array.from(connectorSet).sort().join(', ');
}
} catch {
// Best-effort: if discovery fails, use generic descriptions
}
// Connector names are omitted here to avoid an extra upfront fetchTools()
// call. Descriptions remain generic; tool_execute will fetch tools lazily.
let connectors = '';

Copilot uses AI. Check for mistakes.
Comment on lines +340 to 344
const connectorLine = connectors ? ` Available connectors: ${connectors}.` : '';
const tool = new BaseTool(
'tool_search',
'Search for available tools by describing what you need. Returns matching tool names, descriptions, and parameter schemas. Use the returned parameter schemas to know exactly what to pass when calling tool_execute.',
`Search for available tools by describing what you need. Returns matching tool names, descriptions, and parameter schemas. Use the returned parameter schemas to know exactly what to pass when calling tool_execute.${connectorLine}`,
searchParameters,
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Appending all connector keys into the tool description can grow very large in multi-connector environments, increasing prompt token usage and potentially exceeding provider/tool-description length limits. Consider truncating the list (e.g., max N connectors or max chars) and/or summarizing with “and X more” to keep descriptions bounded.

Copilot uses AI. Check for mistakes.
src/toolsets.ts Outdated
Comment on lines 659 to 673
// Discover available connectors for dynamic descriptions
let connectors = '';
try {
const allTools = await this.fetchTools({ accountIds });
const connectorSet = allTools.getConnectors();
if (connectorSet.size > 0) {
connectors = Array.from(connectorSet).sort().join(', ');
}
} catch {
// Best-effort: if discovery fails, use generic descriptions
}

const searchTool = createSearchTool(this, accountIds, connectors);
const executeTool = createExecuteTool(this, accountIds, connectors);
return new Tools([searchTool, executeTool]);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

There are no tests covering the new dynamic-description behavior (connector discovery success path, sorting/joining, and best-effort failure path). Adding unit tests that assert tool_search/tool_execute descriptions include the connector list when fetchTools() succeeds and remain generic when it throws would help prevent regressions.

Copilot uses AI. Check for mistakes.
@shashi-stackone shashi-stackone changed the title [WIP] Include available connectors in search/execute tool descriptions feat: [WIP] Include available connectors in search/execute tool descriptions Apr 2, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/toolsets.ts">

<violation number="1">
P2: `getTools()` no longer discovers connectors, so `tool_search`/`tool_execute` descriptions remain generic for direct `getTools()` users.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@@ -332,10 +332,15 @@ const localConfig = (id: string): LocalExecuteConfig => ({
});
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 2, 2026

Choose a reason for hiding this comment

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

P2: getTools() no longer discovers connectors, so tool_search/tool_execute descriptions remain generic for direct getTools() users.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/toolsets.ts, line 645:

<comment>`getTools()` no longer discovers connectors, so `tool_search`/`tool_execute` descriptions remain generic for direct `getTools()` users.</comment>

<file context>
@@ -642,32 +642,20 @@ export class StackOneToolSet {
 	 * @returns Tools collection containing tool_search and tool_execute
 	 */
-	async getTools(options?: { accountIds?: string[] }): Promise<Tools> {
+	getTools(options?: { accountIds?: string[] }): Tools {
 		return this.buildTools(options?.accountIds);
 	}
</file context>
Fix with Cubic

Comment on lines +712 to +713
} catch {
// Best-effort: if discovery fails, use generic descriptions
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bare catch in openai() silently swallows errors during connector discovery; add minimal handling such as logging the error or recording telemetry.

Suggested change
} catch {
// Best-effort: if discovery fails, use generic descriptions
} catch (error) {
// Best-effort: if discovery fails, use generic descriptions
console.warn('Failed to discover connectors for tool descriptions:', error);
Details

✨ AI Reasoning
​A new try/catch was added around connector discovery in openai(). The catch clause is a bare catch with no error variable and its body contains only a comment indicating best-effort failure handling. Silent catches can mask unexpected errors and make debugging harder. Even with an explanatory comment, the catch swallows all errors without logging or any observable action, reducing visibility into failures of connector discovery.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 3 files (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

@shashi-stackone shashi-stackone changed the title feat: [WIP] Include available connectors in search/execute tool descriptions feat: Include available connectors in search/execute tool descriptions Apr 7, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="examples/workday-integration.ts">

<violation number="1" location="examples/workday-integration.ts:15">
P2: Do not default `STACKONE_ACCOUNT_ID` to `''`; fail fast (or omit accountIds) when the env var is missing so calls are not scoped to an invalid empty account ID.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 2 unresolved issues from previous reviews.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

willleeney
willleeney previously approved these changes Apr 7, 2026
Copy link
Copy Markdown

@willleeney willleeney left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Copy link
Copy Markdown

@willleeney willleeney left a comment

Choose a reason for hiding this comment

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

lgtm

@shashi-stackone shashi-stackone merged commit 9e731c2 into main Apr 7, 2026
19 checks passed
@shashi-stackone shashi-stackone deleted the feat/dynamic-connector-descriptions branch April 7, 2026 14:57
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.

add utilities test

3 participants