Skip to content
Merged
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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ NucliaDB Agentic API service, and a set of reusable Hyperforge agent packages.

## Packages

The workspace is managed with `uv` and Python 3.10 or newer.
The workspace is managed with `uv` and Python 3.12 or newer.

Core packages:

- `hyperforge`: agentic framework runtime and API.
- `nucliadb_agentic_api`: NucliaDB Agentic API service.

Framework guides:

- [Harness SDK](docs/harness-sdk.md): build asynchronous tool-loop agents with
streaming events, persistence, limits, feedback, memory, and sub-agents.

Agent packages:

- `hyperforge_conditional`
Expand Down Expand Up @@ -120,4 +125,4 @@ Contributions are welcome. Please format the code with `make fmt`, run

[Apache-2.0](LICENSE)

Disclaimer: _This is not an officially supported Progress Software Corporation product._
Disclaimer: _This is not an officially supported Progress Software Corporation product._
1 change: 1 addition & 0 deletions agents/mcp/src/hyperforge_mcp/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ async def preload(self, manager: Manager, memory: QuestionMemory) -> None:
name=tool.name,
description=tool.description or tool.name,
parameters=_tool_parameters(tool.inputSchema),
input_schema=tool.inputSchema,
)
setattr(self, tool.name, self._make_tool_caller(tool.name))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class PerplexitySearchAgent(ContextAgent, Agent[PerplexitySearchAgentConfig]):
__published_functions__: ClassVar[Dict[str, FunctionDefinition]] = {
"internet_search": FunctionDefinition(
name="internet_search",
method="search",
description="Performs an internet search using Perplexity and returns the results as context to answer questions. Does not generate an answer, only search and return the results as context.",
parameters={
"question": {
Expand Down
71 changes: 44 additions & 27 deletions agents/restricted/src/hyperforge_restricted/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

import asyncio
import functools
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
from concurrent.futures import ProcessPoolExecutor
from copy import deepcopy
from dataclasses import dataclass, field
from time import time
from typing import Any, Dict, List, Optional, cast

from hyperforge import logger
from hyperforge.agent import Agent
from hyperforge.codemode import (
RestrictedPythonTask,
SandboxRunner,
WorkerExecutionRequest,
WorkerTypes,
)
from hyperforge.codemode import settings as sandbox_settings
from hyperforge.configure import agent
from hyperforge.context.agent import ContextAgent, build_context_agent
from hyperforge.db.agents import SERVICE_NAME
Expand All @@ -35,14 +42,6 @@
EXTRACT_AGENT_TEMPLATE,
TRANSFORM_REPHRASE,
)
from hyperforge_restricted.model import (
RestrictedPythonTask,
WorkerExecutionRequest,
WorkerTypes,
)

from .sandbox import SandboxRunner
from .sandbox import settings as sandbox_settings


def tracer():
Expand Down Expand Up @@ -81,6 +80,23 @@ class Output:
final_answer: Optional[str] = None


CONTROLLER_FUNCTIONS = {
"add_step",
"choose",
"context_match_question",
"extract",
"rephrase",
"remi_validation",
"save",
"save_context",
"set_context",
"summary",
"transform",
"user_validation",
"validate",
}


if sandbox_settings.sandbox_socket is None:
import os

Expand Down Expand Up @@ -330,19 +346,11 @@ def _runner(self, memory: QuestionMemory, manager: Manager):
sandbox_settings.sandbox_socket,
functools.partial(self.handle_queue_item, manager, memory),
)
elif self.config.debug:
# Debug mode, run in the same process (another thread)
return SandboxRunner.with_pool(
ThreadPoolExecutor(1),
functools.partial(self.handle_queue_item, manager, memory),
debug=True,
)
else:
# Process pool mode, run in a separate process for isolation
return SandboxRunner.with_pool(
SANDBOX_POOL,
functools.partial(self.handle_queue_item, manager, memory),
)
# Process pool mode, run in a separate process for isolation
return SandboxRunner.with_pool(
SANDBOX_POOL,
functools.partial(self.handle_queue_item, manager, memory),
)

async def _preload_child_agents(
self, manager: Manager, memory: QuestionMemory
Expand Down Expand Up @@ -419,11 +427,6 @@ async def _get_question_context(
local_vars["needs_rephrase"] = (
True if depth == 0 and self.config.needs_rephrase else False
)
if self.config.debug:
logger.debug(
f"Executing restricted code, loop {depth}, question: {question}"
)

tasks.append(
asyncio.create_task(
self._runner(memory, manager).run(
Expand Down Expand Up @@ -507,6 +510,20 @@ async def handle_queue_item(
) -> WorkerTypes:
contexts: List[Context] = []

if not (
item.agent == "_controller" and item.function == "save"
) and item.function not in self.function_names.get(item.agent, {}):
raise ValueError(
f"Function {item.function!r} is not authorized for agent {item.agent!r}"
)
if item.function in CONTROLLER_FUNCTIONS and item.agent not in {
"_controller",
"self",
}:
raise ValueError(
f"Function {item.function!r} is reserved for the restricted agent"
)

with tracer().start_as_current_span(f"RestrictedAgent.{item.function}"):
try:
item.keyword_args.update(
Expand Down
10 changes: 0 additions & 10 deletions agents/restricted/src/hyperforge_restricted/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,6 @@ class PythonAgentConfig(ContextAgentConfig):
},
)

debug: bool = Field(
False,
title="Debug mode",
description="Enable debug mode to get more information about the execution",
json_schema_extra={
"show_in_node": False,
"widget": WidgetType.NOT_SHOWN,
},
)

decision_model: LLMField = Field(
default=LLMConfig(model_id=llm_defaults.reasoning),
title="Generative model",
Expand Down
Loading
Loading