agent-framework-github-copilot 1.0.0rc1__tar.gz → 1.0.0rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-framework-github-copilot
3
+ Version: 1.0.0rc2
4
+ Summary: GitHub Copilot integration for Microsoft Agent Framework.
5
+ Author-email: Microsoft <af-support@microsoft.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Typing :: Typed
18
+ License-File: LICENSE
19
+ Requires-Dist: agent-framework-core>=1.10.0,<2
20
+ Requires-Dist: github-copilot-sdk==1.0.2; python_version >= '3.11'
21
+ Project-URL: homepage, https://aka.ms/agent-framework
22
+ Project-URL: issues, https://github.com/microsoft/agent-framework/issues
23
+ Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
24
+ Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
25
+
26
+ # Get Started with Microsoft Agent Framework GitHub Copilot
27
+
28
+ Please install this package via pip:
29
+
30
+ ```bash
31
+ pip install agent-framework-github-copilot --pre
32
+ ```
33
+
34
+ ## GitHub Copilot Agent
35
+
36
+ The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.
37
+
38
+ ## Tool approval (`approval_mode="always_require"`)
39
+
40
+ The GitHub Copilot SDK owns the tool-calling loop for this provider, so approval for
41
+ custom function tools is enforced through the SDK's native pre-execution hook rather
42
+ than the standard Agent Framework approval round-trip.
43
+
44
+ When you register a `FunctionTool` declared with `approval_mode="always_require"` and you
45
+ do **not** supply your own `on_pre_tool_use` hook, `GitHubCopilotAgent` installs a default
46
+ `on_pre_tool_use` hook that returns `"ask"` for that tool and defers (`None`) for all other
47
+ tools. The `"ask"` decision routes to your `on_permission_request` handler, where you
48
+ approve or deny the call:
49
+
50
+ ```python
51
+ from agent_framework import tool
52
+ from agent_framework.github import GitHubCopilotAgent, GitHubCopilotOptions
53
+ from copilot.session import PermissionHandler
54
+
55
+
56
+ @tool(approval_mode="always_require")
57
+ def delete_file(path: str) -> str:
58
+ """Delete a file."""
59
+ ...
60
+
61
+
62
+ agent = GitHubCopilotAgent(
63
+ tools=[delete_file],
64
+ # The "ask" decision is routed here; approve or deny the call.
65
+ default_options=GitHubCopilotOptions(on_permission_request=PermissionHandler.approve_all),
66
+ )
67
+ ```
68
+
69
+ > **⚠️ If you provide your own `on_pre_tool_use` hook**, it takes precedence and the agent
70
+ > does **not** install its default approval hook. In that case **you are fully responsible**
71
+ > for enforcing approval — including for any `approval_mode="always_require"` tool (e.g. by
72
+ > returning a `"deny"` or `"ask"` decision). The agent logs a warning naming any
73
+ > approval-required tool that your hook must handle.
74
+ >
75
+ > Note: with the default (deny-all) permission handler, an `always_require` tool is denied
76
+ > unless you wire an approving `on_permission_request`.
77
+
78
+ ### Deprecated: `on_function_approval`
79
+
80
+ The `on_function_approval` callback is **deprecated**. It still works (and is still enforced
81
+ inside the tool handler for backward compatibility), but it emits a `DeprecationWarning` and
82
+ will be removed in a future version. Migrate to the `on_pre_tool_use` + `on_permission_request`
83
+ model described above. When `on_function_approval` is set, it gates `always_require` tools and
84
+ the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
85
+ setting both (whether at construction or per run) raises `ValueError`.
86
+
87
+
@@ -0,0 +1,61 @@
1
+ # Get Started with Microsoft Agent Framework GitHub Copilot
2
+
3
+ Please install this package via pip:
4
+
5
+ ```bash
6
+ pip install agent-framework-github-copilot --pre
7
+ ```
8
+
9
+ ## GitHub Copilot Agent
10
+
11
+ The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.
12
+
13
+ ## Tool approval (`approval_mode="always_require"`)
14
+
15
+ The GitHub Copilot SDK owns the tool-calling loop for this provider, so approval for
16
+ custom function tools is enforced through the SDK's native pre-execution hook rather
17
+ than the standard Agent Framework approval round-trip.
18
+
19
+ When you register a `FunctionTool` declared with `approval_mode="always_require"` and you
20
+ do **not** supply your own `on_pre_tool_use` hook, `GitHubCopilotAgent` installs a default
21
+ `on_pre_tool_use` hook that returns `"ask"` for that tool and defers (`None`) for all other
22
+ tools. The `"ask"` decision routes to your `on_permission_request` handler, where you
23
+ approve or deny the call:
24
+
25
+ ```python
26
+ from agent_framework import tool
27
+ from agent_framework.github import GitHubCopilotAgent, GitHubCopilotOptions
28
+ from copilot.session import PermissionHandler
29
+
30
+
31
+ @tool(approval_mode="always_require")
32
+ def delete_file(path: str) -> str:
33
+ """Delete a file."""
34
+ ...
35
+
36
+
37
+ agent = GitHubCopilotAgent(
38
+ tools=[delete_file],
39
+ # The "ask" decision is routed here; approve or deny the call.
40
+ default_options=GitHubCopilotOptions(on_permission_request=PermissionHandler.approve_all),
41
+ )
42
+ ```
43
+
44
+ > **⚠️ If you provide your own `on_pre_tool_use` hook**, it takes precedence and the agent
45
+ > does **not** install its default approval hook. In that case **you are fully responsible**
46
+ > for enforcing approval — including for any `approval_mode="always_require"` tool (e.g. by
47
+ > returning a `"deny"` or `"ask"` decision). The agent logs a warning naming any
48
+ > approval-required tool that your hook must handle.
49
+ >
50
+ > Note: with the default (deny-all) permission handler, an `always_require` tool is denied
51
+ > unless you wire an approving `on_permission_request`.
52
+
53
+ ### Deprecated: `on_function_approval`
54
+
55
+ The `on_function_approval` callback is **deprecated**. It still works (and is still enforced
56
+ inside the tool handler for backward compatibility), but it emits a `DeprecationWarning` and
57
+ will be removed in a future version. Migrate to the `on_pre_tool_use` + `on_permission_request`
58
+ model described above. When `on_function_approval` is set, it gates `always_require` tools and
59
+ the default ask-hook is not installed. It is **mutually exclusive** with `on_pre_tool_use` —
60
+ setting both (whether at construction or per run) raises `ValueError`.
61
+
@@ -7,6 +7,7 @@ import contextlib
7
7
  import inspect
8
8
  import logging
9
9
  import sys
10
+ import warnings
10
11
  from collections.abc import AsyncIterable, Awaitable, Callable, Mapping, MutableMapping, Sequence
11
12
  from typing import Any, ClassVar, Generic, Literal, TypedDict, overload
12
13
 
@@ -39,7 +40,15 @@ from agent_framework.observability import AgentTelemetryLayer
39
40
  try:
40
41
  from copilot import CopilotClient, CopilotSession, RuntimeConnection
41
42
  from copilot.generated.rpc import PermissionDecisionUserNotAvailable
42
- from copilot.session import MCPServerConfig, PermissionRequestResult, ProviderConfig, SystemMessageConfig
43
+ from copilot.session import (
44
+ MCPServerConfig,
45
+ PermissionRequestResult,
46
+ PreToolUseHandler,
47
+ PreToolUseHookOutput,
48
+ ProviderConfig,
49
+ SessionHooks,
50
+ SystemMessageConfig,
51
+ )
43
52
  from copilot.session_events import PermissionRequest, SessionEvent, SessionEventType
44
53
  from copilot.tools import Tool as CopilotTool
45
54
  from copilot.tools import ToolInvocation, ToolResult
@@ -50,9 +59,9 @@ except ImportError as _copilot_import_error:
50
59
  ) from _copilot_import_error
51
60
 
52
61
  if sys.version_info >= (3, 13):
53
- from typing import TypeVar
62
+ from typing import TypeVar # pragma: no cover
54
63
  else:
55
- from typing_extensions import TypeVar
64
+ from typing_extensions import TypeVar # pragma: no cover
56
65
 
57
66
 
58
67
  DEFAULT_TIMEOUT_SECONDS: float = 60.0
@@ -65,23 +74,18 @@ PermissionHandlerType = Callable[
65
74
 
66
75
 
67
76
  FunctionApprovalCallback = Callable[[Content], "bool | Awaitable[bool]"]
68
- """Callback invoked by the agent before executing a FunctionTool that requires approval.
77
+ """Deprecated approval callback for ``FunctionTool`` instances declared with
78
+ ``approval_mode="always_require"``.
79
+
80
+ .. deprecated::
81
+ Use the SDK ``on_pre_tool_use`` hook together with ``on_permission_request``
82
+ instead. The default ``on_pre_tool_use`` hook returns ``"ask"`` for
83
+ ``always_require`` tools and routes the decision to ``on_permission_request``.
69
84
 
70
85
  The callback receives a ``FunctionCallContent`` describing the pending call
71
86
  (``name``, ``arguments``, and a synthetic ``call_id``) and must return ``True``
72
87
  to allow execution or ``False`` to deny it. Both synchronous and ``await``-able
73
88
  return values are supported.
74
-
75
- The Copilot CLI manages its own tool-calling loop, so the framework cannot
76
- round-trip a ``FunctionApprovalRequestContent`` / ``FunctionApprovalResponseContent``
77
- pair the way the standard chat-client pipeline does. This callback is the
78
- agent-level enforcement point for tools declared with
79
- ``approval_mode="always_require"``: when no callback is configured the agent
80
- denies these calls by default.
81
-
82
- Note: this is independent of ``on_permission_request``, which gates the
83
- Copilot SDK's *built-in* shell/file actions; ``on_function_approval`` gates
84
- agent-framework ``FunctionTool`` calls.
85
89
  """
86
90
 
87
91
 
@@ -90,7 +94,7 @@ async def _resolve_function_approval(
90
94
  func_tool: FunctionTool,
91
95
  arguments: Mapping[str, Any] | None,
92
96
  ) -> bool:
93
- """Run the agent-level approval callback for a pending tool call.
97
+ """Run the deprecated agent-level approval callback for a pending tool call.
94
98
 
95
99
  Returns ``True`` only when ``callback`` is configured and explicitly returns
96
100
  a truthy value. A missing callback or any callback failure is treated as a
@@ -202,13 +206,39 @@ class GitHubCopilotOptions(TypedDict, total=False):
202
206
  files beyond the default locations.
203
207
  """
204
208
 
209
+ base_directory: str
210
+ """Directory where the CLI stores session state, configuration, and other persistent data."""
211
+
212
+ on_pre_tool_use: PreToolUseHandler
213
+ """Pre-tool-use hook handler for the Copilot SDK.
214
+
215
+ Called by the Copilot SDK before any tool is executed. The handler receives a
216
+ ``PreToolUseHookInput`` and a context dict, and returns a ``PreToolUseHookOutput``
217
+ (or ``None`` to defer). Returning ``{"permissionDecision": "ask"}`` routes the
218
+ decision to ``on_permission_request``; ``"allow"`` / ``"deny"`` gate the call
219
+ directly.
220
+
221
+ If you do **not** supply this hook, the agent installs a default ``on_pre_tool_use``
222
+ hook that returns ``"ask"`` for ``FunctionTool`` instances declared with
223
+ ``approval_mode="always_require"`` (deferring all other tools), so those tools are
224
+ gated through ``on_permission_request``. If you **do** supply your own hook, it
225
+ takes precedence and **you** are responsible for enforcing approval for any
226
+ ``always_require`` tool; the agent logs a warning naming such tools."""
227
+
205
228
  on_function_approval: FunctionApprovalCallback
206
- """Approval callback for ``FunctionTool`` instances declared with
207
- ``approval_mode="always_require"``. The callback is awaited (sync or async)
208
- inside the SDK tool-handler before the tool is executed; a falsy return
209
- value denies the call. If omitted, calls to such tools are denied with an
210
- explanatory message returned to the model. This is independent of
211
- ``on_permission_request``, which gates the Copilot SDK's built-in actions."""
229
+ """Deprecated approval callback for ``FunctionTool`` instances declared with
230
+ ``approval_mode="always_require"``.
231
+
232
+ .. deprecated::
233
+ Use ``on_pre_tool_use`` together with ``on_permission_request`` instead.
234
+ When neither this callback nor ``on_pre_tool_use`` is set, the agent
235
+ installs a default ``on_pre_tool_use`` hook that returns ``"ask"`` for
236
+ ``always_require`` tools and routes the decision to ``on_permission_request``.
237
+
238
+ When set, this callback is enforced inside the SDK tool-handler before the tool
239
+ runs; a falsy return value denies the call. Setting it emits a
240
+ ``DeprecationWarning``. It is **mutually exclusive** with ``on_pre_tool_use`` —
241
+ setting both raises ``ValueError``."""
212
242
 
213
243
 
214
244
  OptionsT = TypeVar(
@@ -316,9 +346,27 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
316
346
  mcp_servers: dict[str, MCPServerConfig] | None = opts.pop("mcp_servers", None)
317
347
  provider: ProviderConfig | None = opts.pop("provider", None)
318
348
  instruction_directories: list[str] | None = opts.pop("instruction_directories", None)
349
+ on_pre_tool_use: PreToolUseHandler | None = opts.pop("on_pre_tool_use", None)
319
350
  on_function_approval: FunctionApprovalCallback | None = opts.pop("on_function_approval", None)
320
351
  base_directory = opts.pop("base_directory", None)
321
352
 
353
+ if on_function_approval is not None and on_pre_tool_use is not None:
354
+ raise ValueError(
355
+ "on_function_approval and on_pre_tool_use cannot both be set. "
356
+ "on_function_approval is deprecated; use on_pre_tool_use together with "
357
+ "on_permission_request instead."
358
+ )
359
+
360
+ if on_function_approval is not None:
361
+ warnings.warn(
362
+ "on_function_approval is deprecated and will be removed in a future version. "
363
+ "Use the SDK 'on_pre_tool_use' hook together with 'on_permission_request' instead: "
364
+ "the default 'on_pre_tool_use' hook returns 'ask' for approval_mode='always_require' "
365
+ "tools and routes the decision to 'on_permission_request'.",
366
+ DeprecationWarning,
367
+ stacklevel=2,
368
+ )
369
+
322
370
  self._settings = load_settings(
323
371
  GitHubCopilotSettings,
324
372
  env_prefix="GITHUB_COPILOT_",
@@ -333,6 +381,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
333
381
 
334
382
  self._tools = normalize_tools(tools)
335
383
  self._permission_handler = on_permission_request
384
+ self._on_pre_tool_use: PreToolUseHandler | None = on_pre_tool_use
336
385
  self._function_approval_handler: FunctionApprovalCallback | None = on_function_approval
337
386
  self._mcp_servers = mcp_servers
338
387
  self._provider = provider
@@ -441,7 +490,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
441
490
  session: AgentSession | None = None,
442
491
  middleware: Sequence[AgentMiddlewareTypes] | None = None,
443
492
  options: OptionsT | None = None,
444
- **kwargs: Any, # type: ignore[override]
493
+ **kwargs: Any,
445
494
  ) -> Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]:
446
495
  """Get a response from the agent.
447
496
 
@@ -519,6 +568,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
519
568
  "via default_options at agent construction time. It cannot be overridden "
520
569
  "per run."
521
570
  )
571
+ if "on_pre_tool_use" in opts and self._function_approval_handler is not None:
572
+ raise ValueError(
573
+ "on_pre_tool_use cannot be combined with the deprecated on_function_approval "
574
+ "(set via default_options). Remove on_function_approval and use on_pre_tool_use "
575
+ "together with on_permission_request instead."
576
+ )
522
577
  timeout = opts.get("timeout") or self._settings.get("timeout") or DEFAULT_TIMEOUT_SECONDS
523
578
 
524
579
  input_messages = normalize_messages(messages)
@@ -608,6 +663,12 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
608
663
  "via default_options at agent construction time. It cannot be overridden "
609
664
  "per run."
610
665
  )
666
+ if "on_pre_tool_use" in opts and self._function_approval_handler is not None:
667
+ raise ValueError(
668
+ "on_pre_tool_use cannot be combined with the deprecated on_function_approval "
669
+ "(set via default_options). Remove on_function_approval and use on_pre_tool_use "
670
+ "together with on_permission_request instead."
671
+ )
611
672
 
612
673
  input_messages = normalize_messages(messages)
613
674
 
@@ -732,7 +793,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
732
793
  if isinstance(provider, HistoryProvider) and not provider.load_messages:
733
794
  continue
734
795
  await provider.before_run(
735
- agent=self, # type: ignore[arg-type]
796
+ agent=self,
736
797
  session=session,
737
798
  context=session_context,
738
799
  state=session.state.setdefault(provider.source_id, {}),
@@ -781,7 +842,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
781
842
  if isinstance(tool, CopilotTool):
782
843
  copilot_tools.append(tool)
783
844
  elif isinstance(tool, FunctionTool):
784
- copilot_tools.append(self._tool_to_copilot_tool(tool)) # type: ignore
845
+ copilot_tools.append(self._tool_to_copilot_tool(tool))
785
846
  elif isinstance(tool, MutableMapping):
786
847
  copilot_tools.append(tool) # type: ignore[arg-type]
787
848
  # Note: Other tool types (e.g., dict-based hosted tools) are skipped
@@ -789,31 +850,32 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
789
850
  return copilot_tools
790
851
 
791
852
  def _tool_to_copilot_tool(self, ai_func: FunctionTool) -> CopilotTool:
792
- """Convert an FunctionTool to a Copilot SDK tool."""
853
+ """Convert an FunctionTool to a Copilot SDK tool.
854
+
855
+ Approval for tools declared with ``approval_mode="always_require"`` is normally
856
+ enforced by the Copilot SDK's native ``on_pre_tool_use`` hook (see
857
+ :meth:`_build_session_hooks`). When the deprecated ``on_function_approval``
858
+ callback is configured instead, approval is enforced inside this handler for
859
+ backward compatibility. (``on_function_approval`` and ``on_pre_tool_use`` are
860
+ mutually exclusive, so only one mechanism is ever active.)
861
+ """
793
862
  approval_handler = self._function_approval_handler
794
- requires_approval = ai_func.approval_mode == "always_require"
863
+ enforce = approval_handler is not None and ai_func.approval_mode == "always_require"
795
864
 
796
865
  async def handler(invocation: ToolInvocation) -> ToolResult:
797
866
  args: dict[str, Any] = invocation.arguments or {}
798
867
  try:
799
- if requires_approval and not await _resolve_function_approval(approval_handler, ai_func, args):
800
- deny_text = (
801
- f"Tool '{ai_func.name}' requires human approval "
802
- "(approval_mode='always_require') and the request was denied."
803
- if approval_handler is not None
804
- else (
805
- f"Tool '{ai_func.name}' requires human approval "
806
- "(approval_mode='always_require') but no on_function_approval "
807
- "callback is configured on the agent; the request was denied."
808
- )
809
- )
868
+ if enforce and not await _resolve_function_approval(approval_handler, ai_func, args):
810
869
  logger.info(
811
- "Denying execution of tool '%s' (approval_mode='always_require', %s)",
870
+ "Denying execution of tool '%s' (approval_mode='always_require', "
871
+ "on_function_approval callback denied).",
812
872
  ai_func.name,
813
- "callback denied" if approval_handler is not None else "no callback configured",
814
873
  )
815
874
  return ToolResult(
816
- text_result_for_llm=deny_text,
875
+ text_result_for_llm=(
876
+ f"Tool '{ai_func.name}' requires human approval "
877
+ "(approval_mode='always_require') and the request was denied."
878
+ ),
817
879
  result_type="failure",
818
880
  error="approval_denied",
819
881
  )
@@ -847,6 +909,80 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
847
909
  parameters=ai_func.parameters(),
848
910
  )
849
911
 
912
+ def _build_session_hooks(
913
+ self,
914
+ all_tools: Sequence[ToolTypes | CopilotTool],
915
+ opts: Mapping[str, Any],
916
+ ) -> SessionHooks | None:
917
+ """Build the ``SessionHooks`` to pass to the Copilot SDK for this session.
918
+
919
+ Approval enforcement for ``FunctionTool`` instances declared with
920
+ ``approval_mode="always_require"`` is delegated to the Copilot SDK's native
921
+ ``on_pre_tool_use`` hook:
922
+
923
+ - If the caller supplies their own ``on_pre_tool_use`` (via per-run ``options``
924
+ or ``default_options``), it takes precedence and is returned unchanged. A
925
+ warning is logged naming any approval-required tool that will therefore not
926
+ be automatically gated, since the caller's hook is responsible for enforcing
927
+ approval.
928
+ - Otherwise, when any approval-required tool is present, a default hook is
929
+ installed that returns ``"ask"`` for those tools (routing the decision to
930
+ ``on_permission_request``) and defers (``None``) for all other tools.
931
+ - The default hook is **not** installed when the deprecated
932
+ ``on_function_approval`` callback is configured: in that case approval is
933
+ enforced inside the tool handler (see :meth:`_tool_to_copilot_tool`) to
934
+ preserve backward-compatible behavior.
935
+ - When there are no approval-required tools and no caller hook, ``None`` is
936
+ returned so no hooks are registered.
937
+
938
+ Args:
939
+ all_tools: The full set of tools resolved for the session.
940
+ opts: Runtime options that take precedence over ``default_options``.
941
+
942
+ Returns:
943
+ The hooks to register for the session, or ``None`` if none are needed.
944
+ """
945
+ user_hook: PreToolUseHandler | None = opts.get("on_pre_tool_use") or self._on_pre_tool_use
946
+
947
+ approval_required_names = {
948
+ tool.name for tool in all_tools if isinstance(tool, FunctionTool) and tool.approval_mode == "always_require"
949
+ }
950
+
951
+ if user_hook is not None:
952
+ if approval_required_names:
953
+ logger.warning(
954
+ "A custom 'on_pre_tool_use' hook is configured, so %d approval-required tool(s) (%s) "
955
+ "will not be automatically gated by GitHubCopilotAgent. The custom hook is responsible "
956
+ "for enforcing approval (for example, by returning a 'deny' or 'ask' decision).",
957
+ len(approval_required_names),
958
+ ", ".join(sorted(approval_required_names)),
959
+ )
960
+ return {"on_pre_tool_use": user_hook}
961
+
962
+ if not approval_required_names:
963
+ return None
964
+
965
+ # The deprecated on_function_approval callback enforces approval in the tool
966
+ # handler; don't also install the default ask-hook (which would double-gate).
967
+ if self._function_approval_handler is not None:
968
+ return None
969
+
970
+ def default_pre_tool_use(
971
+ hook_input: Mapping[str, Any],
972
+ _context: Mapping[str, str],
973
+ ) -> PreToolUseHookOutput | None:
974
+ tool_name = hook_input.get("toolName")
975
+ if tool_name in approval_required_names:
976
+ return {
977
+ "permissionDecision": "ask",
978
+ "permissionDecisionReason": (
979
+ f"Tool '{tool_name}' is marked as requiring approval (approval_mode='always_require')."
980
+ ),
981
+ }
982
+ return None
983
+
984
+ return {"on_pre_tool_use": default_pre_tool_use}
985
+
850
986
  async def _get_or_create_session(
851
987
  self,
852
988
  agent_session: AgentSession,
@@ -904,6 +1040,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
904
1040
  instruction_directories = opts.get("instruction_directories", self._instruction_directories)
905
1041
  all_tools = list(self._tools or []) + list(opts.get("tools") or [])
906
1042
  tools = self._prepare_tools(all_tools) if all_tools else None
1043
+ hooks = self._build_session_hooks(all_tools, opts)
907
1044
 
908
1045
  return await self._client.create_session(
909
1046
  on_permission_request=permission_handler,
@@ -914,6 +1051,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
914
1051
  mcp_servers=mcp_servers or None,
915
1052
  provider=provider or None,
916
1053
  instruction_directories=instruction_directories,
1054
+ hooks=hooks,
917
1055
  )
918
1056
 
919
1057
  async def _resume_session(
@@ -943,6 +1081,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
943
1081
  instruction_directories = opts.get("instruction_directories", self._instruction_directories)
944
1082
  all_tools = list(self._tools or []) + list(opts.get("tools") or [])
945
1083
  tools = self._prepare_tools(all_tools) if all_tools else None
1084
+ hooks = self._build_session_hooks(all_tools, opts)
946
1085
 
947
1086
  return await self._client.resume_session(
948
1087
  session_id,
@@ -954,6 +1093,7 @@ class RawGitHubCopilotAgent(BaseAgent, Generic[OptionsT]):
954
1093
  mcp_servers=mcp_servers or None,
955
1094
  provider=provider or None,
956
1095
  instruction_directories=instruction_directories,
1096
+ hooks=hooks,
957
1097
  )
958
1098
 
959
1099
 
@@ -4,7 +4,7 @@ description = "GitHub Copilot integration for Microsoft Agent Framework."
4
4
  authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
7
- version = "1.0.0rc1"
7
+ version = "1.0.0rc2"
8
8
  license-files = ["LICENSE"]
9
9
  urls.homepage = "https://aka.ms/agent-framework"
10
10
  urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
@@ -23,8 +23,8 @@ classifiers = [
23
23
  "Typing :: Typed",
24
24
  ]
25
25
  dependencies = [
26
- "agent-framework-core>=1.8.0,<2",
27
- "github-copilot-sdk>=1.0.0,<2; python_version >= '3.11'",
26
+ "agent-framework-core>=1.10.0,<2",
27
+ "github-copilot-sdk==1.0.2; python_version >= '3.11'",
28
28
  ]
29
29
 
30
30
  [tool.uv]
@@ -1,37 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: agent-framework-github-copilot
3
- Version: 1.0.0rc1
4
- Summary: GitHub Copilot integration for Microsoft Agent Framework.
5
- Author-email: Microsoft <af-support@microsoft.com>
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Classifier: Programming Language :: Python :: 3.14
17
- Classifier: Typing :: Typed
18
- License-File: LICENSE
19
- Requires-Dist: agent-framework-core>=1.8.0,<2
20
- Requires-Dist: github-copilot-sdk>=1.0.0,<2; python_version >= '3.11'
21
- Project-URL: homepage, https://aka.ms/agent-framework
22
- Project-URL: issues, https://github.com/microsoft/agent-framework/issues
23
- Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
24
- Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
25
-
26
- # Get Started with Microsoft Agent Framework GitHub Copilot
27
-
28
- Please install this package via pip:
29
-
30
- ```bash
31
- pip install agent-framework-github-copilot --pre
32
- ```
33
-
34
- ## GitHub Copilot Agent
35
-
36
- The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.
37
-
@@ -1,11 +0,0 @@
1
- # Get Started with Microsoft Agent Framework GitHub Copilot
2
-
3
- Please install this package via pip:
4
-
5
- ```bash
6
- pip install agent-framework-github-copilot --pre
7
- ```
8
-
9
- ## GitHub Copilot Agent
10
-
11
- The GitHub Copilot agent enables integration with GitHub Copilot, allowing you to interact with Copilot's agentic capabilities through the Agent Framework.