anthropics / anthropics/claude-agent-sdk-python
Claude Agent SDK import hangs under `tsx watch` + `concurrently` on Windows
- Langage dominant
- Python
- Étoiles
- 8.1k
- Forks
- 1.3k
- Métriques de merge des PR
- Métriques de PR en attente
Description
## Summary
Importing `@anthropic-ai/claude-agent-sdk` can cause a Node.js/TypeScript service to hang indefinitely during module initialization when the service is run with `tsx watch` under `concurrently` on Windows.
The same service starts successfully when run directly with `tsx watch`, and also starts successfully when using `concurrently --raw`.
This appears to be an interaction between:
1. Windows process/stdio handling
2. `tsx watch`
3. `concurrently`'s piped/prefixed stdio
4. `@anthropic-ai/claude-agent-sdk`
## Environment
* OS: Windows
* Runtime: Node.js
* TypeScript runner: `tsx`
* Process runner: `concurrently`
* Claude dependency: `@anthropic-ai/claude-agent-sdk`
## Expected behavior
The service should finish importing its dependencies and reach:
```ts
app.listen(4001)
```
regardless of whether it is launched directly or through `concurrently`.
## Actual behavior
When launched through the normal `concurrently` configuration, the ingest process remains alive but hangs during module loading.
It never reaches `app.listen(4001)`.
As a result, nothing is listening on port `4001`, and another service attempting to call the ingest API receives a connection failure.
The process does not appear to crash or throw an exception. It remains alive with negligible CPU activity.
## Process setup
The development command runs three services:
```text
concurrently
├── web → next dev
├── ingest → tsx watch
└── worker → tsx
```
Only the ingest service uses `tsx watch`.
The relevant dependency chain was:
```text
ingest
↓
@relay/agents
↓
providers/claude.ts
↓
@anthropic-ai/claude-agent-sdk
```
## Reproduction / isolation
The issue was isolated by testing the imports individually.
The hang occurs when importing:
```ts
@anthropic-ai/claude-agent-sdk
```
through the Claude provider.
The sibling Gemini provider using:
```ts
@google/genai
```
does not exhibit the same behavior.
### Test 1: Run ingest directly
```bash
tsx watch packages/ingest/src/server.ts
```
Result:
```text
Works
```
The server successfully reaches `app.listen(4001)`.
### Test 2: Run through concurrently
```bash
concurrently ...
```
with the normal piped/prefixed output.
Result:
```text
Hangs during module initialization
```
The process remains alive but never reaches `app.listen(4001)`.
### Test 3: Run through concurrently with `--raw`
```bash
concurrently --raw ...
```
Result:
```text
Works
```
This suggests that `concurrently`'s normal stdio handling/prefixing is involved in the interaction.
## Why this is significant
The Claude provider was statically imported by the provider registry:
```ts
import { ClaudeProvider } from "./providers/claude";
```
Although the registry constructs providers lazily, the static import causes the Claude provider and its dependency tree to be loaded during application startup.
In this application, ingest only uses the analyst and clarifier roles, both of which default to Gemini. A `ClaudeProvider` is therefore not constructed during ingest startup.
The Claude Agent SDK was nevertheless being loaded on every boot.
## Workaround
The Claude provider was changed from an eager static dependency to a dynamic import inside the execution path:
```ts
const { ClaudeProvider } = await import("./providers/claude");
```
This removes the Claude Agent SDK from the ingest/web startup path.
The resulting behavior is:
```text
Application startup
↓
Registry loads
↓
Gemini provider available
↓
app.listen(4001)
↓
Server ready
Claude requested later
↓
dynamic import()
↓
Claude Agent SDK loaded
↓
ClaudeProvider executes
```
This preserves:
* `concurrently`
* prefixed `[web]`, `[ingest]`, `[worker]` logs
* `tsx watch`
* ingest hot reload
without loading the Claude SDK during startup.
## Questions
1. Is `@anthropic-ai/claude-agent-sdk` expected to perform any process/stdio initialization during module import?
2. Could the SDK's initialization interact with piped stdout/stderr or non-TTY streams?
3. Is this combination of Windows + `tsx watch` + `concurrently` known to cause an import hang?
4. If the SDK requires specific stdin/stdout behavior, could the import avoid performing that initialization until the SDK is actually instantiated/used?
5. Is there any recommended configuration for running the SDK under `concurrently` and `tsx watch` on Windows?
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Évaluation
Cette issue n'a pas encore été évaluée.