- Fix issue where mcp tool filtering logic (function_name_filter_list) in admin backend caused all tools to be hidden due to ID prefix mismatch - Force enable web_search tool for Copilot Agent regardless of UI toggles, providing full autonomy for search-related intents - Updated README and version to v0.9.1
7.8 KiB
🤖 Custom Agents Reference (Copilot SDK Python)
This document explains how to create custom agent profiles using the SDK at:
/Users/fujie/app/python/oui/copilot-sdk/python
and apply them in this pipe:
plugins/pipes/github-copilot-sdk/github_copilot_sdk.py
1) What is a “Custom Agent” here?
In Copilot SDK Python, a custom agent is not a separate runtime class from the SDK itself. It is typically a session configuration bundle:
- model + reasoning level
- system message/persona
- tools exposure
- hooks lifecycle behavior
- user input strategy
- infinite session compaction strategy
- provider (optional BYOK)
So the practical implementation is:
- Define an
AgentProfiledata structure. - Convert profile ->
session_config. - Call
client.create_session(session_config).
2) SDK capabilities you can use
From copilot-sdk/python/README.md, the key knobs are:
modelreasoning_efforttoolssystem_messagestreamingproviderinfinite_sessionson_user_input_requesthooks
These are enough to create different agent personas without forking core logic.
3) Recommended architecture in pipe
Use a profile registry + a single factory method.
from dataclasses import dataclass
from typing import Any, Callable, Optional
@dataclass
class AgentProfile:
name: str
model: str
reasoning_effort: str = "medium"
system_message: Optional[str] = None
enable_tools: bool = True
enable_openwebui_tools: bool = True
enable_hooks: bool = False
enable_user_input: bool = False
infinite_sessions_enabled: bool = True
compaction_threshold: float = 0.8
buffer_exhaustion_threshold: float = 0.95
Then map profile -> session config:
def build_session_config(profile: AgentProfile, tools: list, hooks: dict, user_input_handler: Optional[Callable[..., Any]]):
config = {
"model": profile.model,
"reasoning_effort": profile.reasoning_effort,
"streaming": True,
"infinite_sessions": {
"enabled": profile.infinite_sessions_enabled,
"background_compaction_threshold": profile.compaction_threshold,
"buffer_exhaustion_threshold": profile.buffer_exhaustion_threshold,
},
}
if profile.system_message:
config["system_message"] = {"content": profile.system_message}
if profile.enable_tools:
config["tools"] = tools
if profile.enable_hooks and hooks:
config["hooks"] = hooks
if profile.enable_user_input and user_input_handler:
config["on_user_input_request"] = user_input_handler
return config
4) Example profile presets
AGENT_PROFILES = {
"builder": AgentProfile(
name="builder",
model="claude-sonnet-4.6",
reasoning_effort="high",
system_message="You are a precise coding agent. Prefer minimal, verifiable changes.",
enable_tools=True,
enable_hooks=True,
),
"analyst": AgentProfile(
name="analyst",
model="gpt-5-mini",
reasoning_effort="medium",
system_message="You analyze and summarize with clear evidence mapping.",
enable_tools=False,
enable_hooks=False,
),
"reviewer": AgentProfile(
name="reviewer",
model="claude-sonnet-4.6",
reasoning_effort="high",
system_message="Review diffs, identify risks, and propose minimal fixes.",
enable_tools=True,
enable_hooks=True,
),
}
5) Integrating with this pipe
In github_copilot_sdk.py:
- Add a Valve like
AGENT_PROFILE(default:builder). - Resolve profile from registry at runtime.
- Build
session_configfrom profile. - Merge existing valve toggles (
ENABLE_TOOLS,ENABLE_OPENWEBUI_TOOLS) as final override.
Priority recommendation:
- explicit runtime override > valve toggle > profile default
This keeps backward compatibility while enabling profile-based behavior.
6) Hook strategy (safe defaults)
Use hooks only when needed:
on_pre_tool_use: allow/deny tools, sanitize argson_post_tool_use: add short execution contexton_user_prompt_submitted: normalize unsafe prompt patternson_error_occurred: retry/skip/abort policy
Start with no-op hooks, then incrementally enforce policy.
7) Validation checklist
- Profile can be selected by valve and takes effect.
- Session created with expected model/reasoning.
- Tool availability matches profile + valve overrides.
- Hook handlers run only when enabled.
- Infinite-session compaction settings are applied.
- Fallback to default profile if unknown profile name is provided.
8) Anti-patterns to avoid
- Hardcoding profile behavior in multiple places.
- Mixing tool registration logic with prompt-format logic.
- Enabling expensive hooks for all profiles by default.
- Coupling profile name to exact model id with no fallback.
9) Minimal rollout plan
- Add profile dataclass + registry.
- Add one valve:
AGENT_PROFILE. - Build session config factory.
- Keep existing behavior as default profile.
- Add 2 more profiles (
analyst,reviewer) and test.
10) SDK gap analysis for current pipe (high-value missing features)
Current pipe already implements many advanced capabilities:
SessionConfigwithtools,system_message,infinite_sessions,provider,mcp_servers- Session resume/create path
list_models()cache path- Attachments in
session.send(...) - Hook integration (currently
on_post_tool_use)
Still missing (or partially implemented) high-value SDK features:
A. on_user_input_request handler (ask-user loop)
Why valuable
- Enables safe clarification for ambiguous tasks instead of hallucinated assumptions.
Current state
- Not wired into
create_session(...).
Implementation idea
- Add valves:
ENABLE_USER_INPUT_REQUEST: boolDEFAULT_USER_INPUT_ANSWER: str
- Add a handler function and pass:
session_params["on_user_input_request"] = handler
B. Full lifecycle hooks (beyond on_post_tool_use)
Why valuable
- Better policy control and observability.
Current state
- Only
on_post_tool_useimplemented.
Implementation idea
- Add optional handlers for:
on_pre_tool_useon_user_prompt_submittedon_session_starton_session_endon_error_occurred
C. Provider type coverage gap (azure)
Why valuable
- Azure OpenAI users cannot configure provider type natively.
Current state
- Valve type only allows
openai | anthropic.
Implementation idea
- Extend valve enum to include
azure. - Add
BYOK_AZURE_API_VERSIONvalve. - Build
providerpayload withazureblock when selected.
D. Client transport options exposure (cli_url, use_stdio, port)
Why valuable
- Enables remote/shared Copilot server and tuning transport mode.
Current state
_build_client_configsetscli_path/cwd/config_dir/log_level/env, but not transport options.
Implementation idea
- Add valves:
COPILOT_CLI_URLCOPILOT_USE_STDIOCOPILOT_PORT
- Conditionally inject into
client_config.
E. Foreground session lifecycle APIs
Why valuable
- Better multi-session UX and control in TUI/server mode.
Current state
- No explicit usage of:
get_foreground_session_id()set_foreground_session_id()client.on("session.foreground", ...)
Implementation idea
- Optional debug/admin feature only.
- Add event bridge for lifecycle notifications.
11) Recommended implementation priority
on_user_input_request(highest value / low risk)- Full lifecycle hooks (high value / medium risk)
- Azure provider support (high value for enterprise users)
- Client transport valves (
cli_url/use_stdio/port) - Foreground session APIs (optional advanced ops)