Skip to content

Commit 1872a9d

Browse files
zimegClaude
andcommitted
revert: keep current_deps and tool_result in agent/runtime.py
This reverts commit 8742907, so files shared across implementations stay identical. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
1 parent 8742907 commit 1872a9d

25 files changed

Lines changed: 45 additions & 53 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/`. 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.
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.
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/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.
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.
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: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,12 @@ 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, and `current_deps`, which hands them to the tools and hooks since the SDK can't pass them to a tool.
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.
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+
345347
The `workspace.py` file runs commands in the clone without the app's secrets, and keeps file tools inside it.
346348

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.
349+
The `tools` directory contains one file per tool the agents can call.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
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.sessions import AgentDeps, RequestDeps, current_deps
25+
from agent.runtime import current_deps
26+
from agent.sessions import AgentDeps, RequestDeps
2627
from agent.tools import (
2728
archive_channel,
2829
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.sessions import current_deps
28+
from agent.runtime import current_deps
2929

3030
logger = getLogger(__name__)
3131

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""What the tools and hooks share during a run: its deps, and the shape of a tool result.
2+
3+
The Claude Agent SDK calls a tool with only its arguments, so `agent/agent.py`
4+
sets the run's deps here before each run starts, and the tools and the hooks in
5+
`agent/guardrails.py` read them back.
6+
"""
7+
8+
from contextvars import ContextVar
9+
10+
from agent.sessions import AgentDeps, RequestDeps
11+
12+
current_deps: ContextVar[AgentDeps | RequestDeps] = ContextVar("current_deps")
13+
14+
15+
def tool_result(text: str) -> dict:
16+
"""A tool's reply to the model."""
17+
return {"content": [{"type": "text", "text": text}]}

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
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. 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.
10+
code channel, and `RequestDeps` for a request outside one.
1411
"""
1512

1613
import asyncio
1714
import shutil
18-
from contextvars import ContextVar
1915
from dataclasses import dataclass, field
2016

2117
from slack_sdk.web.async_client import AsyncWebClient
@@ -83,9 +79,6 @@ class RequestDeps:
8379
code_channel_id: str | None = None
8480

8581

86-
current_deps: ContextVar[AgentDeps | RequestDeps] = ContextVar("current_deps")
87-
88-
8982
class CodeChannelSessionStore:
9083
"""In-memory store of active code channel sessions."""
9184

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
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-
71
from .archive_channel import archive_channel
82
from .clone_repo import clone_repo
93
from .create_code_channel import create_code_channel

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

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

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

76
DESCRIPTION = """\
87
Post a final summary and archive the code channel.

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

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

66
from claude_agent_sdk import tool
77

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

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

0 commit comments

Comments
 (0)