HalClient: GitHub Copilot SDK Client

HalClientR Documentation

GitHub Copilot SDK Client

Description

Manages the Copilot CLI subprocess in ACP (Agent Client Protocol) mode and handles JSON-RPC 2.0 communication over NDJSON stdio. This is the low-level transport layer – most users should use HalChat instead.

The client spawns the Copilot CLI with --acp, which starts it as a JSON-RPC server. Authentication uses ambient Copilot credentials from any editor (VS Code, Positron, JetBrains).

Value

An R6 object of class HalClient. Methods return values as documented per method; construct with HalClient$new().

Methods

Public methods


HalClient$new()

Create a new Copilot SDK client.

Usage
HalClient$new(
  model = NULL,
  cli_path = NULL,
  permission_policy = "auto-allow",
  on_text = NULL,
  on_tool_call = NULL,
  on_thought = NULL,
  quiet = FALSE
)
Arguments
model

Model identifier (e.g., "claude-sonnet-5", "gpt-5.2"). Passed as --model to the CLI at startup. If NULL, falls back to the COPILOT_MODEL environment variable, then the server default.

cli_path

Path to the Copilot CLI binary. If NULL, searches PATH and common install locations.

permission_policy

How to handle tool permission requests: "auto-allow" (default) auto-approves all, "auto-deny" auto-denies, or a function receiving the permission params and returning an option ID.

on_text

Callback function receiving each text chunk as it streams. Signature: ⁠function(chunk)⁠. Called for each agent_message_chunk.

on_tool_call

Callback function receiving tool call events. Signature: ⁠function(tool_call)⁠. Called on tool_call and tool_call_update events with a hal_tool_call object.

on_thought

Callback function receiving thought chunks. Signature: ⁠function(chunk)⁠. Called for each agent_thought_chunk.

quiet

Logical; suppress informational messages during init, handshake, and session creation (default: FALSE).


HalClient$start()

Start the Copilot CLI subprocess in ACP mode.

Usage
HalClient$start()
Returns

Invisibly returns self.


HalClient$stop()

Stop the Copilot CLI subprocess.

Usage
HalClient$stop()

HalClient$register_tools()

Register tools to expose via MCP server.

Tools must be registered before the first ⁠$prompt()⁠ call (before the CLI subprocess starts). The tools are passed via --additional-mcp-config at startup. Registering tools after the CLI is running triggers a warning.

Tools are merged into the existing set by name. Call multiple times to accumulate tools from different sources.

Usage
HalClient$register_tools(tools)
Arguments
tools

Named list of tool definitions.

Returns

Invisibly returns self.


HalClient$handshake()

Perform the ACP initialize handshake.

Sends the initialize request and initialized notification. Called automatically on first use if needed.

Usage
HalClient$handshake(timeout = 15)
Arguments
timeout

Timeout in seconds.

Returns

The initialize result (agent info and capabilities).


HalClient$new_session()

Create a new ACP session.

Sends session/new to create a session. The session holds conversation state server-side. Automatically performs the handshake if needed.

Custom tools are configured via --additional-mcp-config at CLI startup (not via mcpServers in this call, which is broken per CLI issue #1040).

Usage
HalClient$new_session(cwd = getwd(), timeout = 15)
Arguments
cwd

Working directory to report to the server.

timeout

Timeout in seconds.

Returns

The session result (session ID, available models, modes).


HalClient$prompt()

Send a prompt and collect the streamed response.

Sends session/prompt and reads session/update notifications until the final response arrives. Automatically creates a session if needed.

Usage
HalClient$prompt(text, timeout = NULL)
Arguments
text

The prompt text.

timeout

Timeout in seconds.

Returns

A hal_response with text, stop_reason, tool_calls, thoughts, and events.


HalClient$request()

Send a JSON-RPC request and wait for a response.

Usage
HalClient$request(method, params = list(), timeout = 60)
Arguments
method

JSON-RPC method name.

params

Named list of parameters.

timeout

Timeout in seconds.

Returns

Parsed JSON response result.


HalClient$notify()

Send a JSON-RPC notification (no response expected).

Usage
HalClient$notify(method, params = list())
Arguments
method

JSON-RPC method name.

params

Named list of parameters.


HalClient$switch_model()

Switch models mid-session.

Changes the active model without losing conversation context. Use hal_models() to see available model IDs.

Usage
HalClient$switch_model(model, timeout = 10)
Arguments
model

Model identifier (e.g., "gpt-4.1", "claude-haiku-4.5").

timeout

Timeout in seconds.

Returns

Invisibly returns self.


HalClient$set_mode()

Set the session mode.

Switches between Agent, Plan, and Autopilot modes.

  • Agent: Default conversational mode.

  • Plan: Multi-step planning mode with structured output.

  • Autopilot: Autonomous mode that runs until task completion without user interaction (experimental).

Usage
HalClient$set_mode(mode = c("agent", "plan", "autopilot"), timeout = 10)
Arguments
mode

"agent", "plan", or "autopilot".

timeout

Timeout in seconds.

Returns

Invisibly returns self.


HalClient$get_session_id()

Get the current session ID.

Usage
HalClient$get_session_id()
Returns

Character string, or NULL if no session is active.


HalClient$swap_session()

Create a temporary new session, saving the current one.

Used internally by disposable verbs (hal_ask) to get history isolation on the same CLI process. Call restore_session() to switch back.

Usage
HalClient$swap_session()
Returns

The saved (previous) session ID (invisibly).


HalClient$restore_session()

Restore a previously saved session ID.

Usage
HalClient$restore_session(session_id)
Arguments
session_id

The session ID returned by swap_session().

Returns

Invisibly returns self.


HalClient$cancel()

Cancel the current in-flight prompt.

Signals the streaming loop to stop and return a partial response with stop_reason = "interrupted". Safe to call from callbacks, Shiny observers, or a second thread. Does nothing if no prompt is active.

For interactive use, pressing Ctrl+C (ESC in RStudio) during a prompt achieves the same effect automatically.

Usage
HalClient$cancel()
Returns

Invisibly returns self.


HalClient$set_ipc()

Configure IPC for live eval_r execution.

When set, the polling loop checks for eval_r requests from the MCP subprocess and executes them in the user's R session via eval_fn.

Usage
HalClient$set_ipc(ipc_dir, eval_fn = NULL, permission_fn = NULL)
Arguments
ipc_dir

Path to the IPC directory for request/response files.

eval_fn

Function taking a code string and returning list(result = "...", error = NULL) or list(result = NULL, error = "...").

permission_fn

Optional handler for permission requests (used by the Claude permission_prompt bridge). Takes the parsed request object and returns the same list(result, error) shape as eval_fn.

Returns

Invisibly returns self.


HalClient$is_alive()

Check if the client subprocess is running.

Usage
HalClient$is_alive()
Returns

Logical.


HalClient$read_stderr()

Read any available stderr output (for debugging).

Usage
HalClient$read_stderr()
Returns

Character string.


HalClient$clone()

The objects of this class are cloneable with this method.

Usage
HalClient$clone(deep = FALSE)
Arguments
deep

Whether to make a deep clone.

See Also

HalChat for the high-level chat interface, hal_available() to check CLI availability.

Examples

## Not run: 
# Preferred: use hal_client()
client <- hal_client()
client$handshake()
session <- client$new_session()
client$stop()

## End(Not run)


hal documentation built on Oct. 6, 2026, 5:07 p.m.