Skip to content

Commit 8742907

Browse files
zimegClaude
andcommitted
refactor: move current_deps to sessions and tool_result to tools
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
1 parent 4f1c6eb commit 8742907

25 files changed

Lines changed: 53 additions & 45 deletions

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The flow: a mention or direct message outside a code channel runs a small routin
5555
Implementations share structure, not code, so these parts are kept the same by copying them and changing them everywhere at once:
5656

5757
- **The seam between `listeners/` and `agent/`.** Listeners import only from the `agent` package, never from the agent framework, so `listeners/` is the same in every implementation. `agent/__init__.py` provides `answer_request`, `find_session`, `run_turn`, `resume_turn`, `stop_turn`, and `end_session`.
58-
- **Framework-free files.** `agent/turns.py`, `agent/context.py`, `agent/approvals.py`, `agent/sessions.py`, `agent/workspace.py`, `agent/outcome.py`, and `agent/prompts.py` don't import the agent framework. The framework lives in `agent/agent.py`, `agent/guardrails.py`, and `agent/tools/`, and the Claude Agent SDK adds `agent/runtime.py` for the deps its tools can't be passed. `turns.py` calls only `run_request(prompt, deps)`, which returns the reply text, and `start_run(history, text, deps)` and `resume_run(paused, approved, deps)`, which return the `RunOutcome` in `agent/outcome.py`. The paused run is a handle `turns.py` passes back without looking inside, so each framework's way of pausing fits behind it.
58+
- **Framework-free files.** `agent/turns.py`, `agent/context.py`, `agent/approvals.py`, `agent/sessions.py`, `agent/workspace.py`, `agent/outcome.py`, and `agent/prompts.py` don't import the agent framework. The framework lives in `agent/agent.py`, `agent/guardrails.py`, and `agent/tools/`. The Claude Agent SDK's `agent/sessions.py` also holds `current_deps`, for the deps its tools can't be passed, so keep it there when copying changes to that file. `turns.py` calls only `run_request(prompt, deps)`, which returns the reply text, and `start_run(history, text, deps)` and `resume_run(paused, approved, deps)`, which return the `RunOutcome` in `agent/outcome.py`. The paused run is a handle `turns.py` passes back without looking inside, so each framework's way of pausing fits behind it.
5959
- **What the framework side keeps true.** `turns.py` relies on these, so every implementation keeps them: `create_code_channel` sets `deps.code_channel_id`, and `archive_channel` sets `session.archived`. Every code channel tool skips its call once `session.stopped` is set. `turns.py` can drop a paused run without resuming it, since the session's history then shows its pending command as not run: the history already records it that way, or the next run answers it that way before anything else. Beyond that, `turns.py` only checks whether `history` is empty, to know a turn is the first.
6060
- **Prompts.** `agent/prompts.py` is the same word for word in every implementation.
6161
- **Tools.** Every implementation offers the same tools with the same names, arguments, and descriptions, written with its framework's tool decorator. File tools stay inside the clone and can't write into `.git`.

‎claude-agent-sdk/AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Guidance for coding agents working in this directory. Refer to the root `../AGEN
66

77
**Agents (`agent/agent.py`)** are two sets of `ClaudeAgentOptions` with pinned models: a routing agent (`claude-haiku-4-5`) whose only tool is `create_code_channel`, and the coding agent (`claude-sonnet-5-5`) with every other tool. Tools are async `@tool` functions, one per file under `agent/tools/`, each with a JSON Schema for its arguments. They're served in-process by `create_sdk_mcp_server()`, so the model sees each as `mcp__coding-agent__<name>`. Both agents set `tools=[]`, `setting_sources=[]`, and `strict_mcp_config=True`, so they get none of Claude Code's built-in tools and none of the settings, `CLAUDE.md` files, or MCP servers on the machine. `verbatim_prompts=True` keeps an `@path` in a Slack message from reading a local file.
88

9-
**Deps** reach the tools and hooks through `current_deps` in `agent/runtime.py`, a `ContextVar`, since the SDK calls a tool with only its arguments. `_run` in `agent/agent.py` sets it before the client starts, so the tasks the client starts see it.
9+
**Deps** reach the tools and hooks through `current_deps` in `agent/sessions.py`, a `ContextVar`, since the SDK calls a tool with only its arguments. `_run` in `agent/agent.py` sets it before the client starts, so the tasks the client starts see it.
1010

1111
**Runs** use a `ClaudeSDKClient` per run from async Bolt listeners, which runs the Claude Code CLI bundled with the SDK. Coding turns allow `MAX_TURNS` model calls, and a turn that uses them all (`error_max_turns`) ends with a message, keeping its history. A `PostToolUse` hook returns `continue_: False` to end the run early once there's nothing left to do: after `create_code_channel` succeeds for the routing agent, and after `archive_channel` for the coding agent. A result with `is_error` raises, so the turn posts a warning.
1212

‎claude-agent-sdk/README.md‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,12 +338,10 @@ The `context.py` file reads the thread or direct message a request came from, so
338338

339339
The `guardrails.py` file holds the SDK hooks that gate tool calls: the approval check for `run_command`, which defers a command that needs approval, and the check that skips every tool call once the session is stopped.
340340

341-
The `sessions.py` file keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` dataclasses passed to the agents at runtime, providing access to the Slack client and the session or request.
341+
The `sessions.py` file keeps each code channel's session in memory: its working directory, plan canvas, conversation history, and messages waiting for the next turn. It also defines the `AgentDeps` and `RequestDeps` dataclasses passed to the agents at runtime, providing access to the Slack client and the session or request, and `current_deps`, which hands them to the tools and hooks since the SDK can't pass them to a tool.
342342

343343
The `approvals.py` file decides which commands need approval and holds runs paused on one.
344344

345-
The `runtime.py` file holds what the tools and hooks share during a run: its deps, which the SDK can't pass to a tool, and the shape of a tool's reply.
346-
347345
The `workspace.py` file runs commands in the clone without the app's secrets, and keeps file tools inside it.
348346

349-
The `tools` directory contains one file per tool the agents can call.
347+
The `tools` directory contains one file per tool the agents can call, and `tool_result` in its `__init__.py` for the shape of a tool's reply.

‎claude-agent-sdk/agent/agent.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
from agent.guardrails import answer_unanswered, gate_tool_calls
2323
from agent.outcome import RunOutcome
2424
from agent.prompts import REQUEST_PROMPT, SYSTEM_PROMPT
25-
from agent.runtime import current_deps
26-
from agent.sessions import AgentDeps, RequestDeps
25+
from agent.sessions import AgentDeps, RequestDeps, current_deps
2726
from agent.tools import (
2827
archive_channel,
2928
clone_repo,

‎claude-agent-sdk/agent/guardrails.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626

2727
from agent.approvals import command_needs_approval
28-
from agent.runtime import current_deps
28+
from agent.sessions import current_deps
2929

3030
logger = getLogger(__name__)
3131

‎claude-agent-sdk/agent/runtime.py‎

Lines changed: 0 additions & 17 deletions
This file was deleted.

‎claude-agent-sdk/agent/sessions.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
when its channel is archived.
88
99
The deps passed to each agent run live here too: `AgentDeps` for a turn in a
10-
code channel, and `RequestDeps` for a request outside one.
10+
code channel, and `RequestDeps` for a request outside one. The Claude Agent SDK
11+
calls a tool with only its arguments, so `agent/agent.py` sets the run's deps in
12+
`current_deps` before each run starts, and the tools and the hooks in
13+
`agent/guardrails.py` read them back.
1114
"""
1215

1316
import asyncio
1417
import shutil
18+
from contextvars import ContextVar
1519
from dataclasses import dataclass, field
1620

1721
from slack_sdk.web.async_client import AsyncWebClient
@@ -79,6 +83,9 @@ class RequestDeps:
7983
code_channel_id: str | None = None
8084

8185

86+
current_deps: ContextVar[AgentDeps | RequestDeps] = ContextVar("current_deps")
87+
88+
8289
class CodeChannelSessionStore:
8390
"""In-memory store of active code channel sessions."""
8491

‎claude-agent-sdk/agent/tools/__init__.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Defined before the tool imports below, since each tool imports it from here.
2+
def tool_result(text: str) -> dict:
3+
"""A tool's reply to the model."""
4+
return {"content": [{"type": "text", "text": text}]}
5+
6+
17
from .archive_channel import archive_channel
28
from .clone_repo import clone_repo
39
from .create_code_channel import create_code_channel

‎claude-agent-sdk/agent/tools/archive_channel.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from claude_agent_sdk import tool
22
from slack_sdk.errors import SlackApiError
33

4-
from agent.runtime import current_deps, tool_result
4+
from agent.sessions import current_deps
5+
from agent.tools import tool_result
56

67
DESCRIPTION = """\
78
Post a final summary and archive the code channel.

‎claude-agent-sdk/agent/tools/clone_repo.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
from claude_agent_sdk import tool
77

8-
from agent.runtime import current_deps, tool_result
8+
from agent.sessions import current_deps
9+
from agent.tools import tool_result
910
from agent.workspace import run
1011

1112
# Cap the clone so an unreachable or huge repository can't wedge the session.

0 commit comments

Comments
 (0)