Skip to content

Commit 0b6a41d

Browse files
author
NGUYEN Duc Trung
committed
feat: support custom tools in subagents
All three SDKs (Go, Python, Node) use per-session tool handler lookup keyed to the exact session ID. When the CLI creates child sessions for subagents, those child session IDs are never registered in the SDK's sessions map. Tool calls arriving with a child session ID fail with "unknown session". This PR adds the ability to call custom tools for sub-agents in Go, following the proposal in #947
1 parent e3638da commit 0b6a41d

File tree

7 files changed

+1123
-35
lines changed

7 files changed

+1123
-35
lines changed

go/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,58 @@ safeLookup := copilot.DefineTool("safe_lookup", "A read-only lookup that needs n
359359
safeLookup.SkipPermission = true
360360
```
361361

362+
### Custom Tools with Subagents
363+
364+
When a session is configured with both custom tools and custom agents (subagents), the
365+
subagents can invoke the parent session's custom tools. The SDK automatically routes
366+
tool calls from child sessions back to the parent session's tool handlers.
367+
368+
#### Tool Access Control
369+
370+
The `Tools` field on `CustomAgentConfig` controls which custom tools each subagent can access:
371+
372+
| `Tools` value | Behavior |
373+
|---------------|----------|
374+
| `nil` (default) | Subagent can access **all** custom tools registered on the parent session |
375+
| `[]string{}` (empty) | Subagent cannot access **any** custom tools |
376+
| `[]string{"tool_a", "tool_b"}` | Subagent can only access the listed tools |
377+
378+
#### Example
379+
380+
```go
381+
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
382+
Tools: []copilot.Tool{
383+
copilot.DefineTool("save_output", "Saves output to storage",
384+
func(params SaveParams, inv copilot.ToolInvocation) (string, error) {
385+
// Handle tool call — works for both direct and subagent invocations
386+
return saveToStorage(params.Content)
387+
}),
388+
copilot.DefineTool("get_data", "Retrieves data from storage",
389+
func(params GetParams, inv copilot.ToolInvocation) (string, error) {
390+
return getData(params.Key)
391+
}),
392+
},
393+
CustomAgents: []copilot.CustomAgentConfig{
394+
{
395+
Name: "researcher",
396+
Description: "Researches topics and saves findings",
397+
Tools: []string{"save_output"}, // Can only use save_output, not get_data
398+
Prompt: "You are a research assistant. Save your findings using save_output.",
399+
},
400+
{
401+
Name: "analyst",
402+
Description: "Analyzes data from storage",
403+
Tools: nil, // Can access ALL custom tools
404+
Prompt: "You are a data analyst.",
405+
},
406+
},
407+
})
408+
```
409+
410+
When `researcher` is invoked as a subagent, it can call `save_output` but not `get_data`.
411+
When `analyst` is invoked, it can call both tools. If a subagent attempts to use a tool
412+
not in its allowlist, the SDK returns a `"Tool '{name}' is not supported by this client instance."` response to the LLM.
413+
362414
## Streaming
363415

364416
Enable streaming to receive assistant response chunks as they're generated:

0 commit comments

Comments
 (0)