Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,23 @@ The `sgrsh` command:

For more examples and detailed usage instructions, see the [examples/](examples/) directory.

### Agent Client Protocol (`sgracp`)

Editors and tools that speak the [Agent Client Protocol](https://agentclientprotocol.com/) can run SGR agents over **stdio** (newline-delimited JSON-RPC), using the same YAML configuration as the HTTP server.

```bash
sgracp --config examples/sgr_deep_research/config.yaml
```

Optional `acp` block in `config.yaml` selects which `agents:` entry to expose (if omitted, the first agent definition is used):

```yaml
acp:
agent: sgr_agent
```

Protocol details follow the official ACP specification, the [Python SDK](https://agentclientprotocol.github.io/python-sdk/), and the `agent-client-protocol` package used by this binary.

## Benchmarking

![SimpleQA Benchmark Comparison](https://github.com/vamplabAI/sgr-agent-core/blob/main/docs/assets/images/simpleqa_benchmark_comparison.png)
Expand Down
4 changes: 4 additions & 0 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ execution:
logs_dir: "logs" # Directory for saving agent execution logs
reports_dir: "reports" # Directory for saving agent reports

# Optional: Agent Client Protocol (stdio) via `sgracp --config config.yaml`
# acp:
# agent: "sgr_agent" # Must match a name under agents:

# Prompts Configuration
# prompts:
# # Option 1: Use file paths (absolute or relative to project root)
Expand Down
17 changes: 17 additions & 0 deletions docs/en/framework/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ config = GlobalConfig.from_yaml("config.yaml")

An example can be found in [`config.yaml.example`](https://github.com/vamplabAI/sgr-agent-core/blob/main/config.yaml.example).

### Agent Client Protocol (`sgracp`)

The optional top-level `acp` section configures the [`sgracp`](https://github.com/vamplabAI/sgr-agent-core) stdio entrypoint (Agent Client Protocol over stdin/stdout). It uses the same `agents:` definitions as the rest of the stack.

| Field | Description |
| ----- | ----------- |
| `agent` | Name of an entry under `agents:` to run when a client connects. If omitted, the first agent in `agents:` is used. |

Example:

```yaml
acp:
agent: sgr_agent
```

You can also set `SGR__ACP__AGENT` in the environment (see `pydantic-settings` nested env rules for your version).

### Parameter Override

**Key Feature:** `AgentDefinition` inherits all parameters from `GlobalConfig` and overrides only those explicitly specified. This allows creating minimal configurations by specifying only necessary changes.
Expand Down
15 changes: 15 additions & 0 deletions docs/ru/framework/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,22 @@ config = GlobalConfig.from_yaml("config.yaml")

Пример можно найти в [`config.yaml.example`](https://github.com/vamplabAI/sgr-agent-core/blob/main/config.yaml.example).

### Agent Client Protocol (`sgracp`)

Необязательная секция верхнего уровня `acp` задаёт параметры для stdio-входа [`sgracp`](https://github.com/vamplabAI/sgr-agent-core) (Agent Client Protocol поверх stdin/stdout). Используются те же определения `agents:`, что и для HTTP API.

| Поле | Описание |
| ---- | -------- |
| `agent` | Имя записи в `agents:` для запуска при подключении клиента. Если не задано, берётся первый агент из `agents:`. |

Пример:

```yaml
acp:
agent: sgr_agent
```

Переменную окружения можно задать как `SGR__ACP__AGENT` (см. правила вложенных переменных в `pydantic-settings` для вашей версии).

### Переопределение параметров

Expand Down
44 changes: 0 additions & 44 deletions examples/sgr_deep_research/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from sgr_agent_core.agent_definition import AgentConfig
from sgr_agent_core.agents.dialog_agent import DialogAgent
from sgr_agent_core.agents.iron_agent import IronAgent
from sgr_agent_core.agents.sgr_agent import SGRAgent
from sgr_agent_core.agents.sgr_tool_calling_agent import SGRToolCallingAgent
from sgr_agent_core.agents.tool_calling_agent import ToolCallingAgent
from sgr_agent_core.tools import (
Expand All @@ -24,54 +23,11 @@
ExtractPageContentTool,
FinalAnswerTool,
NextStepToolsBuilder,
NextStepToolStub,
ReasoningTool,
WebSearchTool,
)


class ResearchSGRAgent(SGRAgent):
"""Agent for deep research tasks."""

def __init__(
self,
task_messages: list[ChatCompletionMessageParam],
openai_client: AsyncOpenAI,
agent_config: AgentConfig,
toolkit: list[Type[BaseTool]],
def_name: str | None = None,
**kwargs: dict,
):
research_toolkit = [WebSearchTool, ExtractPageContentTool, CreateReportTool, FinalAnswerTool]
super().__init__(
task_messages=task_messages,
openai_client=openai_client,
agent_config=agent_config,
toolkit=research_toolkit + [t for t in toolkit if t not in research_toolkit],
def_name=def_name,
**kwargs,
)

async def _prepare_tools(self) -> Type[NextStepToolStub]:
"""Prepare available tools for the current agent state and progress."""
tools = set(self.toolkit)
if self._context.iteration >= self.config.execution.max_iterations:
tools = {
CreateReportTool,
FinalAnswerTool,
}
if self._context.clarifications_used >= self.config.execution.max_clarifications:
tools -= {
ClarificationTool,
}
search_config = self.get_tool_config(WebSearchTool)
if self._context.searches_used >= search_config.max_searches:
tools -= {
WebSearchTool,
}
return NextStepToolsBuilder.build_NextStepTools(list(tools))


class ResearchToolCallingAgent(ToolCallingAgent):
"""Tool calling research agent for deep research tasks."""

Expand Down
18 changes: 4 additions & 14 deletions examples/sgr_deep_research/config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ execution:
logs_dir: "logs" # Directory for saving agent execution logs
reports_dir: "reports" # Directory for saving research reports

# Agent Client Protocol (ACP)
acp:
agent: tool_calling_agent

# MCP (Model Context Protocol) Configuration
mcp:
mcpServers:
Expand Down Expand Up @@ -54,20 +58,6 @@ tools:

# Agent Definitions
agents:
# SGR Agent for research
sgr_agent:
base_class: "agents.ResearchSGRAgent"
llm:
model: "gpt-4.1-mini"
temperature: 0.4
tools:
- "web_search_tool"
- "extract_page_content_tool"
- "create_report_tool"
- "final_answer_tool"
- "clarification_tool"
- "generate_plan_tool"
- "adapt_plan_tool"

# Tool Calling Agent for research
tool_calling_agent:
Expand Down
83 changes: 22 additions & 61 deletions examples/sgr_file_agent/config.yaml.example
Original file line number Diff line number Diff line change
@@ -1,55 +1,26 @@
# SGR File Agent - Configuration Template
# Copy this file to config.yaml and fill in your data
# Smoke test for sgracp + sgr_file_agent (see scripts/smoke_acp_file_agent.py)
# LLM matches OpenAI-compatible endpoint; paths are relative to this file.

# LLM Configuration
llm:
api_key: "your-openai-api-key-here" # Your OpenAI API key
base_url: "https://api.openai.com/v1" # API base URL
model: "gpt-4o-mini" # Model name
max_tokens: 8000 # Max output tokens
temperature: 0.4 # Temperature (0.0-1.0)
# proxy: "socks5://127.0.0.1:1081" # Optional proxy (socks5:// or http://)
api_key: "https://t.me/evilfreelancer"
base_url: "https://api.rpa.icu/v1"
model: "gpt-oss:120b"
max_tokens: 4000
temperature: 0.3

# Execution Settings
execution:
max_clarifications: 3 # Max clarification requests
max_iterations: 10 # Max agent iterations
mcp_context_limit: 15000 # Max context length from MCP server response
logs_dir: "logs" # Directory for saving agent execution logs
reports_dir: "reports" # Directory for saving agent reports
max_clarifications: 1
max_iterations: 3
mcp_context_limit: 15000
logs_dir: "logs"
reports_dir: "reports"

# Prompts Configuration
# prompts:
# # Option 1: Use file paths (absolute or relative to project root)
# system_prompt_file: "path/to/your/system_prompt.txt"
# initial_user_request_file: "path/to/your/initial_user_request.txt"
# clarification_response_file: "path/to/your/clarification_response.txt"
#
# # Option 2: Provide prompts directly as strings
# system_prompt_str: "Your custom system prompt here..."
# initial_user_request_str: "Your custom initial request template..."
# clarification_response_str: "Your custom clarification template..."

# Note: If both file and string are provided, string takes precedence

# MCP (Model Context Protocol) Configuration
mcp:
mcpServers: {}
# Add MCP servers here if needed:
# deepwiki:
# url: "https://mcp.deepwiki.com/mcp"

# Tool Definitions
tools:
# Core tools (base_class defaults to sgr_agent_core.tools.*)
reasoning_tool:
# base_class defaults to sgr_agent_core.tools.ReasoningTool
clarification_tool:
# base_class defaults to sgr_agent_core.tools.ClarificationTool
final_answer_tool:
# base_class defaults to sgr_agent_core.tools.FinalAnswerTool

# File system tools - using relative imports (relative to config.yaml location)
clarification_tool: {}
final_answer_tool: {}
get_system_paths_tool:
base_class: "tools.GetSystemPathsTool"
list_directory_tool:
Expand All @@ -61,34 +32,24 @@ tools:
find_files_fast_tool:
base_class: "tools.FindFilesFastTool"

# Agent Definitions
agents:
sgr_file_agent:
base_class: "sgr_file_agent.SGRFileAgent" # Relative to config.yaml location
# Optional: Override LLM settings for this agent
llm:
model: "gpt-4o-mini"
temperature: 0.4
max_tokens: 8000

# Execution configuration
base_class: "sgr_file_agent.SGRFileAgent"
execution:
max_iterations: 15
max_clarifications: 3
max_searches: 0 # File agent doesn't use web search
max_iterations: 3
max_clarifications: 1
max_searches: 0
logs_dir: "logs/file_agent"
reports_dir: "reports/file_agent"

# Agent-specific parameters (for SGRFileAgent)
working_directory: "." # Working directory for file operations (default: current directory)

# Tools this agent can use (names from tools section above)
working_directory: "."
tools:
- "reasoning_tool"
- "clarification_tool"
- "final_answer_tool"
- "get_system_paths_tool"
- "list_directory_tool"
- "read_file_tool"
- "search_in_files_tool"
- "find_files_fast_tool"

acp:
agent: sgr_file_agent
24 changes: 11 additions & 13 deletions examples/sgr_file_agent/sgr_file_agent.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from typing import Type

from openai import AsyncOpenAI
from openai import AsyncOpenAI, pydantic_function_tool
from openai.types.chat import ChatCompletionFunctionToolParam

from sgr_agent_core.agent_definition import AgentConfig
from sgr_agent_core.agents.sgr_agent import SGRAgent
from sgr_agent_core.next_step_tool import NextStepToolsBuilder, NextStepToolStub
from sgr_agent_core.agents.tool_calling_agent import ToolCallingAgent
from sgr_agent_core.tools import (
BaseTool,
ClarificationTool,
Expand All @@ -21,9 +21,10 @@
)


class SGRFileAgent(SGRAgent):
"""File-first agent that uses OpenAI native function calling to work with filesystem.
Two-phase agent: reasoning phase + action phase.
class SGRFileAgent(ToolCallingAgent):
"""File-first agent using native function calling only (no separate
reasoning round-trip). Suited for OpenAI-compatible endpoints that handle
tool_choice reliably but not structured reasoning schemas.

Focus: File search and analysis (read-only operations)

Expand Down Expand Up @@ -92,12 +93,9 @@ def __init__(
working_directory = getattr(agent_config, "working_directory", ".")
self.working_directory = working_directory

async def _prepare_tools(self) -> Type[NextStepToolStub]:
"""Prepare available tools for current agent state and progress.

Returns NextStepToolStub class for response_format, filtering
tools based on agent state.
"""
async def _prepare_tools(self) -> list[ChatCompletionFunctionToolParam]:
"""Build function-calling tool list for each step (filter by iteration
limits)."""
tools = set(self.toolkit)
if self._context.iteration >= self.config.execution.max_iterations:
tools = {
Expand All @@ -108,4 +106,4 @@ async def _prepare_tools(self) -> Type[NextStepToolStub]:
tools -= {
ClarificationTool,
}
return NextStepToolsBuilder.build_NextStepTools(list(tools))
return [pydantic_function_tool(tool, name=tool.tool_name) for tool in tools]
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies = [
"jambo>=0.1.3.post2",
# Tools filtering
"rank-bm25>=0.2.2",
"agent-client-protocol>=0.9.0",
]

[project.urls]
Expand All @@ -66,6 +67,7 @@ Documentation = "https://vamplabai.github.io/sgr-agent-core/"
[project.scripts]
sgr = "sgr_agent_core.server.__main__:main"
sgrsh = "sgr_agent_core.cli.__main__:main"
sgracp = "sgr_agent_core.acp.__main__:main"

[project.optional-dependencies]
dev = [
Expand Down
5 changes: 5 additions & 0 deletions sgr_agent_core/acp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Agent Client Protocol (ACP) stdio integration for SGR Agent Core."""

from sgr_agent_core.acp.bridge import SGRACPBridge, extract_prompt_text

__all__ = ["SGRACPBridge", "extract_prompt_text"]
Loading
Loading