anycode-py 0.1.0__py3-none-any.whl

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.
anycode/types.py ADDED
@@ -0,0 +1,313 @@
1
+ """AnyCode — Pydantic models for the entire type surface."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import AsyncIterable, Awaitable, Callable
6
+ from datetime import datetime
7
+ from typing import Any, Literal, Protocol, runtime_checkable
8
+
9
+ from pydantic import BaseModel, ConfigDict
10
+
11
+ # -- Content blocks --
12
+
13
+ class TextBlock(BaseModel):
14
+ model_config = ConfigDict(frozen=True)
15
+ type: Literal["text"] = "text"
16
+ text: str
17
+
18
+
19
+ class ToolUseBlock(BaseModel):
20
+ model_config = ConfigDict(frozen=True)
21
+ type: Literal["tool_use"] = "tool_use"
22
+ id: str
23
+ name: str
24
+ input: dict[str, Any]
25
+
26
+
27
+ class ToolResultBlock(BaseModel):
28
+ model_config = ConfigDict(frozen=True)
29
+ type: Literal["tool_result"] = "tool_result"
30
+ tool_use_id: str
31
+ content: str
32
+ is_error: bool | None = None
33
+
34
+
35
+ class ImageSource(BaseModel):
36
+ model_config = ConfigDict(frozen=True)
37
+ type: Literal["base64"] = "base64"
38
+ media_type: str
39
+ data: str
40
+
41
+
42
+ class ImageBlock(BaseModel):
43
+ model_config = ConfigDict(frozen=True)
44
+ type: Literal["image"] = "image"
45
+ source: ImageSource
46
+
47
+
48
+ ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ImageBlock
49
+
50
+
51
+ # -- Conversation messages --
52
+
53
+ class LLMMessage(BaseModel):
54
+ model_config = ConfigDict(frozen=True)
55
+ role: Literal["user", "assistant"]
56
+ content: list[ContentBlock]
57
+
58
+
59
+ class TokenUsage(BaseModel):
60
+ model_config = ConfigDict(frozen=True)
61
+ input_tokens: int = 0
62
+ output_tokens: int = 0
63
+
64
+
65
+ class LLMResponse(BaseModel):
66
+ model_config = ConfigDict(frozen=True)
67
+ id: str
68
+ content: list[ContentBlock]
69
+ model: str
70
+ stop_reason: str
71
+ usage: TokenUsage
72
+
73
+
74
+ class StreamEvent(BaseModel):
75
+ model_config = ConfigDict(frozen=True)
76
+ type: Literal["text", "tool_use", "tool_result", "done", "error"]
77
+ data: Any
78
+
79
+
80
+ # -- Tool definitions --
81
+
82
+ class LLMToolDef(BaseModel):
83
+ model_config = ConfigDict(frozen=True)
84
+ name: str
85
+ description: str
86
+ input_schema: dict[str, Any]
87
+
88
+
89
+ class ToolResult(BaseModel):
90
+ model_config = ConfigDict(frozen=True)
91
+ data: str
92
+ is_error: bool | None = None
93
+
94
+
95
+ class AgentInfo(BaseModel):
96
+ model_config = ConfigDict(frozen=True)
97
+ name: str
98
+ role: str
99
+ model: str
100
+
101
+
102
+ class TeamInfo(BaseModel):
103
+ model_config = ConfigDict(frozen=True)
104
+ name: str
105
+ agents: list[str]
106
+
107
+
108
+ class ToolUseContext(BaseModel):
109
+ model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
110
+ agent: AgentInfo
111
+ team: TeamInfo | None = None
112
+ cwd: str | None = None
113
+ metadata: dict[str, Any] | None = None
114
+
115
+
116
+ class ToolDefinition(BaseModel):
117
+ """A tool with a Pydantic model for input validation and an async execute function."""
118
+
119
+ model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
120
+ name: str
121
+ description: str
122
+ input_model: type[BaseModel]
123
+ execute: Callable[..., Awaitable[ToolResult]]
124
+
125
+
126
+ # -- Agent configuration --
127
+
128
+ class AgentConfig(BaseModel):
129
+ model_config = ConfigDict(frozen=True)
130
+ name: str
131
+ model: str
132
+ provider: Literal["anthropic", "openai"] | None = None
133
+ system_prompt: str | None = None
134
+ tools: list[str] | None = None
135
+ max_turns: int | None = None
136
+ max_tokens: int | None = None
137
+ temperature: float | None = None
138
+
139
+
140
+ class AgentState(BaseModel):
141
+ status: Literal["idle", "running", "completed", "error"] = "idle"
142
+ messages: list[LLMMessage] = []
143
+ token_usage: TokenUsage = TokenUsage()
144
+ error: str | None = None
145
+
146
+
147
+ class ToolCallRecord(BaseModel):
148
+ model_config = ConfigDict(frozen=True)
149
+ tool_name: str
150
+ input: dict[str, Any]
151
+ output: str
152
+ duration: float
153
+
154
+
155
+ class AgentRunResult(BaseModel):
156
+ model_config = ConfigDict(frozen=True)
157
+ success: bool
158
+ output: str
159
+ messages: list[LLMMessage]
160
+ token_usage: TokenUsage
161
+ tool_calls: list[ToolCallRecord]
162
+
163
+
164
+ # -- Team --
165
+
166
+ class TeamConfig(BaseModel):
167
+ model_config = ConfigDict(frozen=True)
168
+ name: str
169
+ agents: list[AgentConfig]
170
+ shared_memory: bool | None = None
171
+ max_concurrency: int | None = None
172
+
173
+
174
+ class TeamRunResult(BaseModel):
175
+ model_config = ConfigDict(frozen=True)
176
+ success: bool
177
+ agent_results: dict[str, AgentRunResult]
178
+ total_token_usage: TokenUsage
179
+
180
+
181
+ # -- Tasks --
182
+
183
+ TaskStatus = Literal["pending", "in_progress", "completed", "failed", "blocked"]
184
+
185
+
186
+ class Task(BaseModel):
187
+ id: str
188
+ title: str
189
+ description: str
190
+ status: TaskStatus = "pending"
191
+ assignee: str | None = None
192
+ depends_on: list[str] | None = None
193
+ result: str | None = None
194
+ created_at: datetime
195
+ updated_at: datetime
196
+
197
+
198
+ # -- Orchestrator --
199
+
200
+ class OrchestratorEvent(BaseModel):
201
+ model_config = ConfigDict(frozen=True)
202
+ type: Literal["agent_start", "agent_complete", "task_start", "task_complete", "message", "error"]
203
+ agent: str | None = None
204
+ task: str | None = None
205
+ data: Any = None
206
+
207
+
208
+ class OrchestratorConfig(BaseModel):
209
+ model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
210
+ max_concurrency: int | None = None
211
+ default_model: str | None = None
212
+ default_provider: Literal["anthropic", "openai"] | None = None
213
+ on_progress: Callable[[OrchestratorEvent], None] | None = None
214
+
215
+
216
+ # -- Memory --
217
+
218
+ class MemoryEntry(BaseModel):
219
+ model_config = ConfigDict(frozen=True)
220
+ key: str
221
+ value: str
222
+ metadata: dict[str, Any] | None = None
223
+ created_at: datetime
224
+
225
+
226
+ @runtime_checkable
227
+ class MemoryStore(Protocol):
228
+ """Async key-value store interface."""
229
+
230
+ async def get(self, key: str) -> MemoryEntry | None: ...
231
+ async def set(self, key: str, value: str, metadata: dict[str, Any] | None = None) -> None: ...
232
+ async def list(self) -> list[MemoryEntry]: ...
233
+ async def delete(self, key: str) -> None: ...
234
+ async def clear(self) -> None: ...
235
+
236
+
237
+ # -- LLM adapter --
238
+
239
+ class LLMChatOptions(BaseModel):
240
+ model_config = ConfigDict(frozen=True)
241
+ model: str
242
+ tools: list[LLMToolDef] | None = None
243
+ max_tokens: int | None = None
244
+ temperature: float | None = None
245
+ system_prompt: str | None = None
246
+
247
+
248
+ class LLMStreamOptions(LLMChatOptions):
249
+ pass
250
+
251
+
252
+ @runtime_checkable
253
+ class LLMAdapter(Protocol):
254
+ """Provider-agnostic LLM interface."""
255
+
256
+ @property
257
+ def name(self) -> str: ...
258
+ async def chat(self, messages: list[LLMMessage], options: LLMChatOptions) -> LLMResponse: ...
259
+ def stream(self, messages: list[LLMMessage], options: LLMStreamOptions) -> AsyncIterable[StreamEvent]: ...
260
+
261
+
262
+ # -- Runner types --
263
+
264
+ class RunnerOptions(BaseModel):
265
+ model_config = ConfigDict(frozen=True)
266
+ model: str
267
+ system_prompt: str | None = None
268
+ max_turns: int | None = None
269
+ max_tokens: int | None = None
270
+ temperature: float | None = None
271
+ allowed_tools: list[str] | None = None
272
+ agent_name: str | None = None
273
+ agent_role: str | None = None
274
+
275
+
276
+ class RunResult(BaseModel):
277
+ model_config = ConfigDict(frozen=True)
278
+ messages: list[LLMMessage]
279
+ output: str
280
+ tool_calls: list[ToolCallRecord]
281
+ token_usage: TokenUsage
282
+ turns: int
283
+
284
+
285
+ class PoolStatus(BaseModel):
286
+ model_config = ConfigDict(frozen=True)
287
+ total: int
288
+ idle: int
289
+ running: int
290
+ completed: int
291
+ error: int
292
+
293
+
294
+ SchedulingStrategy = Literal["round-robin", "least-busy", "capability-match", "dependency-first"]
295
+
296
+
297
+ class Message(BaseModel):
298
+ model_config = ConfigDict(frozen=True)
299
+ id: str
300
+ from_agent: str
301
+ to_agent: str
302
+ content: str
303
+ timestamp: datetime
304
+
305
+
306
+ TaskQueueEvent = Literal["task:ready", "task:complete", "task:failed", "all:complete"]
307
+
308
+
309
+ class BatchToolCall(BaseModel):
310
+ model_config = ConfigDict(frozen=True)
311
+ id: str
312
+ name: str
313
+ input: dict[str, Any]
@@ -0,0 +1,399 @@
1
+ Metadata-Version: 2.4
2
+ Name: anycode-py
3
+ Version: 0.1.0
4
+ Summary: Orchestrate autonomous AI agent teams with dependency-aware task scheduling, inter-agent messaging, and provider-agnostic LLM integration.
5
+ Project-URL: Homepage, https://github.com/Quantlix/anycode
6
+ Project-URL: Repository, https://github.com/Quantlix/anycode
7
+ Project-URL: Issues, https://github.com/Quantlix/anycode/issues
8
+ Author: Quantlix
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai,anthropic,llm,multi-agent,openai,orchestration,task-scheduling,team-collaboration,tool-use
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: anthropic>=0.40
21
+ Requires-Dist: openai>=1.50
22
+ Requires-Dist: pydantic>=2.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ <p align="center">
26
+ <img src="https://img.shields.io/pypi/v/anycode?style=flat-square&color=0078D4" alt="PyPI version" />
27
+ <img src="https://img.shields.io/pypi/l/anycode?style=flat-square" alt="license" />
28
+ <img src="https://img.shields.io/badge/Python-3.12+-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python" />
29
+ <img src="https://img.shields.io/badge/Built%20by-Quantlix-blueviolet?style=flat-square" alt="Built by Quantlix" />
30
+ </p>
31
+
32
+ # AnyCode
33
+
34
+ ### Scalable Multi-Agent AI Orchestration Framework for Python
35
+
36
+ > Developed and maintained by **[Quantlix](https://github.com/Quantlix)**
37
+
38
+ AnyCode is a lightweight yet powerful orchestration engine written entirely in Python. It enables you to compose autonomous AI agents into collaborative teams that communicate, share context, resolve task dependencies, and operate concurrently — all from a single runtime. Whether you're deploying on bare metal, inside containers, across serverless functions, or within CI/CD pipelines, AnyCode adapts to your infrastructure without friction.
39
+
40
+ Instead of managing individual agents in silos, AnyCode introduces a team-oriented paradigm: agents exchange messages through a built-in event bus, persist shared knowledge in memory stores, and execute work items according to a topologically sorted task graph. The result is a cohesive system where every agent understands its role and collaborates toward a unified objective.
41
+
42
+ ---
43
+
44
+ ## Table of Contents
45
+
46
+ - [Key Capabilities](#key-capabilities)
47
+ - [Quick Start](#quick-start)
48
+ - [Building Agent Teams](#building-agent-teams)
49
+ - [Defining Task Pipelines](#defining-task-pipelines)
50
+ - [Creating Custom Tools](#creating-custom-tools)
51
+ - [Cross-Provider Model Mixing](#cross-provider-model-mixing)
52
+ - [Live Streaming Output](#live-streaming-output)
53
+ - [Architecture Overview](#architecture-overview)
54
+ - [Built-In Tool Reference](#built-in-tool-reference)
55
+ - [Core Concepts at a Glance](#core-concepts-at-a-glance)
56
+ - [Contributing](#contributing)
57
+ - [License](#license)
58
+
59
+ ---
60
+
61
+ ## Key Capabilities
62
+
63
+ Traditional agent libraries focus on running a single LLM in a loop. AnyCode takes a fundamentally different approach — it gives you **an entire coordinated team**:
64
+
65
+ | Feature | Description |
66
+ |---------|-------------|
67
+ | **Inter-agent communication** | Agents relay information through `MessageBus`, share persistent state via `SharedMemory`, and synchronize through managed task queues |
68
+ | **Dependency-driven execution** | Express task relationships with `depends_on` and let `TaskQueue` resolve ordering through topological sorting — no manual sequencing needed |
69
+ | **Automatic goal decomposition** | Provide a high-level objective and the orchestrator intelligently partitions it into targeted subtasks assigned to the right agents |
70
+ | **Provider-agnostic design** | Seamlessly use Anthropic Claude, OpenAI GPT, or integrate any custom backend through the `LLMAdapter` protocol |
71
+ | **Schema-validated tooling** | Every tool is declared with a Pydantic model for input validation, plus five practical tools are included out of the box |
72
+ | **Bounded parallelism** | Independent work items execute simultaneously, governed by a configurable concurrency semaphore |
73
+ | **Flexible scheduling strategies** | Choose between round-robin, least-busy, capability-match, or dependency-first assignment policies |
74
+ | **Incremental streaming** | Receive real-time text deltas from any agent as an `AsyncGenerator[StreamEvent, None]` |
75
+ | **Full type safety** | Strict Pydantic models enforced at every layer, with validation at all external boundaries |
76
+
77
+ ---
78
+
79
+ ## Quick Start
80
+
81
+ Install the package from PyPI:
82
+
83
+ ```bash
84
+ pip install anycode
85
+ # or with uv
86
+ uv add anycode
87
+ ```
88
+
89
+ ### Single Agent Execution
90
+
91
+ The simplest way to get started — spin up one agent and hand it a task:
92
+
93
+ ```python
94
+ import asyncio
95
+ from anycode import AnyCode
96
+
97
+ async def main():
98
+ engine = AnyCode()
99
+
100
+ result = await engine.run_agent(
101
+ config={
102
+ "name": "engineer",
103
+ "model": "claude-sonnet-4-6",
104
+ "tools": ["bash", "file_write"],
105
+ },
106
+ prompt="Create a Python utility that checks whether a given string is a palindrome, save it to /tmp/palindrome.py, and execute it.",
107
+ )
108
+
109
+ print(result.output)
110
+
111
+ asyncio.run(main())
112
+ ```
113
+
114
+ > **Note:** Export `ANTHROPIC_API_KEY` and/or `OPENAI_API_KEY` as environment variables before running any example.
115
+
116
+ ---
117
+
118
+ ## Building Agent Teams
119
+
120
+ Real-world workflows benefit from specialization. AnyCode lets you define distinct agents — each with its own system prompt, model, and tool access — and unify them into a collaborative team:
121
+
122
+ ```python
123
+ import asyncio
124
+ from anycode import AnyCode, AgentConfig, TeamConfig
125
+
126
+ planner = AgentConfig(
127
+ name="planner",
128
+ model="claude-sonnet-4-6",
129
+ system_prompt="You draft module interfaces, folder layouts, and endpoint schemas.",
130
+ tools=["file_write"],
131
+ )
132
+
133
+ builder = AgentConfig(
134
+ name="builder",
135
+ model="claude-sonnet-4-6",
136
+ system_prompt="You translate specifications into production-ready code.",
137
+ tools=["bash", "file_read", "file_write", "file_edit"],
138
+ )
139
+
140
+ auditor = AgentConfig(
141
+ name="auditor",
142
+ model="claude-sonnet-4-6",
143
+ system_prompt="You inspect code for bugs, edge cases, and readability concerns.",
144
+ tools=["file_read", "grep"],
145
+ )
146
+
147
+ async def main():
148
+ engine = AnyCode(config={
149
+ "default_model": "claude-sonnet-4-6",
150
+ "on_progress": lambda ev: print(ev.type, ev.agent or ev.task or ""),
151
+ })
152
+
153
+ team = engine.create_team("backend-crew", TeamConfig(
154
+ name="backend-crew",
155
+ agents=[planner, builder, auditor],
156
+ shared_memory=True,
157
+ ))
158
+
159
+ result = await engine.run_team(team, "Scaffold a CRUD API for a notes app in /tmp/notes-api/")
160
+
161
+ print(f"Completed: {result.success}")
162
+ print(f"Tokens used: {result.total_token_usage.output_tokens}")
163
+
164
+ asyncio.run(main())
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Defining Task Pipelines
170
+
171
+ For workflows that demand precise control over the execution graph, you can manually specify tasks along with their dependencies:
172
+
173
+ ```python
174
+ from anycode import TaskSpec
175
+
176
+ result = await engine.run_tasks(team, [
177
+ TaskSpec(
178
+ title="Draft schema definitions",
179
+ description="Produce Python type declarations and save them to /tmp/types.md",
180
+ assignee="planner",
181
+ ),
182
+ TaskSpec(
183
+ title="Implement core logic",
184
+ description="Read /tmp/types.md and build the service layer in /tmp/lib/",
185
+ assignee="builder",
186
+ depends_on=["Draft schema definitions"],
187
+ ),
188
+ TaskSpec(
189
+ title="Write unit tests",
190
+ description="Author pytest test suites covering all service methods.",
191
+ assignee="builder",
192
+ depends_on=["Implement core logic"],
193
+ ),
194
+ TaskSpec(
195
+ title="Audit implementation",
196
+ description="Examine /tmp/lib/ and generate a detailed review report.",
197
+ assignee="auditor",
198
+ depends_on=["Implement core logic"],
199
+ ),
200
+ ])
201
+ ```
202
+
203
+ The `TaskQueue` resolves the dependency graph using topological sorting. Tasks with no unmet dependencies are dispatched in parallel, while dependent tasks wait until their predecessors complete successfully.
204
+
205
+ ---
206
+
207
+ ## Creating Custom Tools
208
+
209
+ Extend agent capabilities by registering your own tools. Each tool is defined with a Pydantic model for automatic validation:
210
+
211
+ ```python
212
+ from pydantic import BaseModel, Field
213
+ from anycode import define_tool, Agent, ToolRegistry, ToolExecutor, register_built_in_tools, ToolResult, ToolUseContext
214
+
215
+ class ArticleSearchInput(BaseModel):
216
+ topic: str = Field(description="Subject to search for.")
217
+ limit: int = Field(default=5, description="Maximum articles to return.")
218
+
219
+ async def fetch_articles(params: ArticleSearchInput, ctx: ToolUseContext) -> ToolResult:
220
+ articles = await my_knowledge_base(params.topic, params.limit)
221
+ return ToolResult(data=json.dumps(articles), is_error=False)
222
+
223
+ fetch_articles_tool = define_tool(
224
+ name="fetch_articles",
225
+ description="Retrieves relevant articles from the knowledge base.",
226
+ input_model=ArticleSearchInput,
227
+ execute=fetch_articles,
228
+ )
229
+
230
+ registry = ToolRegistry()
231
+ register_built_in_tools(registry)
232
+ registry.register(fetch_articles_tool)
233
+
234
+ executor = ToolExecutor(registry)
235
+ agent = Agent(
236
+ config={"name": "analyst", "model": "claude-sonnet-4-6", "tools": ["fetch_articles"]},
237
+ tool_registry=registry,
238
+ tool_executor=executor,
239
+ )
240
+
241
+ result = await agent.run("Summarize the latest changes in the Python typing module.")
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Cross-Provider Model Mixing
247
+
248
+ Combine different LLM providers within a single team. Assign a reasoning-heavy model to your strategist and a fast coding model to your implementer:
249
+
250
+ ```python
251
+ thinker = AgentConfig(
252
+ name="thinker",
253
+ model="claude-opus-4-6",
254
+ provider="anthropic",
255
+ system_prompt="You devise architectural blueprints and technical strategies.",
256
+ tools=["file_write"],
257
+ )
258
+
259
+ implementer = AgentConfig(
260
+ name="implementer",
261
+ model="gpt-4o",
262
+ provider="openai",
263
+ system_prompt="You transform plans into functional, tested code.",
264
+ tools=["bash", "file_read", "file_write"],
265
+ )
266
+
267
+ team = engine.create_team("cross-provider", TeamConfig(
268
+ name="cross-provider",
269
+ agents=[thinker, implementer],
270
+ shared_memory=True,
271
+ ))
272
+
273
+ await engine.run_team(team, "Create a CLI utility that transforms YAML files into JSON format.")
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Live Streaming Output
279
+
280
+ For interactive applications or real-time feedback, stream agent output token-by-token:
281
+
282
+ ```python
283
+ import asyncio
284
+ import sys
285
+ from anycode import Agent, ToolRegistry, ToolExecutor, register_built_in_tools
286
+
287
+ async def main():
288
+ registry = ToolRegistry()
289
+ register_built_in_tools(registry)
290
+ executor = ToolExecutor(registry)
291
+
292
+ narrator = Agent(
293
+ config={"name": "narrator", "model": "claude-sonnet-4-6", "max_turns": 3},
294
+ tool_registry=registry,
295
+ tool_executor=executor,
296
+ )
297
+
298
+ async for ev in narrator.stream("Describe the observer pattern in three sentences."):
299
+ if ev.type == "text" and isinstance(ev.data, str):
300
+ sys.stdout.write(ev.data)
301
+
302
+ asyncio.run(main())
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Architecture Overview
308
+
309
+ ```
310
+ +--------------------------------------------------------------+
311
+ | AnyCode (orchestrator) |
312
+ | |
313
+ | create_team() · run_team() · run_tasks() · run_agent()|
314
+ +-----------------------------+--------------------------------+
315
+ |
316
+ +----------v----------+
317
+ | Team |
318
+ | AgentConfig[] |
319
+ | MessageBus |
320
+ | TaskQueue |
321
+ | SharedMemory |
322
+ +----------+----------+
323
+ |
324
+ +-------------+-------------+
325
+ | |
326
+ +--------v---------+ +------------v-----------+
327
+ | AgentPool | | TaskQueue |
328
+ | Semaphore | | dependency graph |
329
+ | run_parallel() | | cascade failure |
330
+ +--------+---------+ +------------------------+
331
+ |
332
+ +--------v---------+
333
+ | Agent | +------------------------+
334
+ | run / prompt / |--->| LLMAdapter |
335
+ | stream | | Anthropic · OpenAI |
336
+ +--------+---------+ +------------------------+
337
+ |
338
+ +--------v---------+
339
+ | AgentRunner | +------------------------+
340
+ | conversation |--->| ToolRegistry |
341
+ | loop + dispatch | | define_tool + 5 |
342
+ +------------------+ | built-in tools |
343
+ +------------------------+
344
+ ```
345
+
346
+ **Data flow summary:**
347
+
348
+ 1. The **orchestrator** receives a goal or an explicit task list
349
+ 2. A **Team** manages the agent roster, message bus, and shared memory
350
+ 3. The **AgentPool** dispatches work using a bounded concurrency semaphore
351
+ 4. The **TaskQueue** resolves dependencies via topological sort and cascades failures
352
+ 5. Each **Agent** runs a conversation loop through **AgentRunner**, invoking tools from the **ToolRegistry** as needed
353
+ 6. LLM calls are routed through the **LLMAdapter** abstraction, supporting any provider
354
+
355
+ ---
356
+
357
+ ## Built-In Tool Reference
358
+
359
+ AnyCode ships with five practical tools that cover the most common agent operations:
360
+
361
+ | Tool | What It Does |
362
+ |------|-------------|
363
+ | `bash` | Executes shell commands with stdout/stderr capture, configurable timeout, and working-directory support |
364
+ | `file_read` | Reads file contents from an absolute path, with optional offset and line-limit for handling large files |
365
+ | `file_write` | Creates or overwrites a file at the specified path — parent directories are generated automatically |
366
+ | `file_edit` | Performs targeted substring replacement within a file, with an option to replace all occurrences |
367
+ | `grep` | Runs regex-based searches across files, leveraging ripgrep when available or falling back to a pure Python implementation |
368
+
369
+ All tools follow the same `define_tool()` pattern, so extending or replacing them works identically to registering custom tools.
370
+
371
+ ---
372
+
373
+ ## Core Concepts at a Glance
374
+
375
+ | Concept | Component | Responsibility |
376
+ |---------|-----------|----------------|
377
+ | Conversation loop | `AgentRunner` | Manages the model <-> tool turn cycle until the task completes |
378
+ | Typed tool declaration | `define_tool()` | Defines tools with Pydantic-validated input models |
379
+ | Orchestration | `AnyCode` | Decomposes goals, assigns work, and manages concurrency |
380
+ | Team coordination | `Team` + `MessageBus` | Enables inter-agent messaging and shared knowledge state |
381
+ | Task scheduling | `TaskQueue` | Resolves execution order through topological dependency sorting |
382
+
383
+ ---
384
+
385
+ ## Contributing
386
+
387
+ Contributions, suggestions, and issue reports are welcome. Please open an issue or submit a pull request on the [GitHub repository](https://github.com/Quantlix/anycode).
388
+
389
+ ---
390
+
391
+ ## License
392
+
393
+ Released under the MIT License — see [LICENSE](./LICENSE) for details.
394
+
395
+ ---
396
+
397
+ <p align="center">
398
+ Built with purpose by <strong><a href="https://github.com/Quantlix">Quantlix</a></strong>
399
+ </p>