mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-18 03:33:59 -05:00
Integrate feature into agent system (#111)
This commit integrates the LEITL (Live Everyone In The Loop) Protocol
and Cece Cognition Framework into the BlackRoad agent ecosystem,
enabling multi-agent collaboration and advanced reasoning capabilities.
**Changes:**
1. **Cognition Router Integration**
(`backend/app/routers/cognition.py`):
- Fixed import path for orchestration service
- Exposes full Cece Cognition Framework via REST API
- Endpoints for single agent execution and multi-agent workflows
- Supports sequential, parallel, and recursive execution modes
2. **Main App Updates** (`backend/app/main.py`):
- Added cognition router to imports
- Registered `/api/cognition` endpoints
- Added Cognition tag to OpenAPI docs
3. **BaseAgent LEITL Integration** (`agents/base/agent.py`):
- Added optional LEITL protocol support to base agent class
- New methods: `enable_leitl()`, `disable_leitl()`,
`_leitl_broadcast()`, `_leitl_heartbeat()`
- Automatic event broadcasting during agent execution lifecycle
- Events: task.started, task.completed, task.failed
- Heartbeat support for session keep-alive
4. **AgentRegistry LEITL Support** (`agents/base/registry.py`):
- Added `enable_leitl_for_all()` - Enable LEITL for all registered
agents
- Added `disable_leitl_for_all()` - Disable LEITL for all agents
- Added `get_leitl_status()` - Get LEITL status and session IDs
- Bulk agent session management
**Integration Architecture:**
```
User Request → Cognition API (/api/cognition)
↓
Orchestration Engine
↓
┌────────────┴──────────┐
↓ ↓
Cece Agent Other Agents
(15-step reasoning) (specialized)
↓ ↓
LEITL Protocol (if enabled)
↓
Redis PubSub + WebSocket
↓
Other active sessions
```
**New Capabilities:**
1. **Single Agent Execution**: POST /api/cognition/execute
- Execute Cece, Wasp, Clause, or Codex individually
- Full reasoning trace and confidence scores
2. **Multi-Agent Workflows**: POST /api/cognition/workflows
- Orchestrate multiple agents in complex workflows
- Sequential, parallel, or recursive execution
- Shared memory and context across agents
3. **LEITL Collaboration**:
- All agents can now broadcast their activity in real-time
- Multi-agent sessions can see each other's work
- Live activity feed via WebSocket
- Session management with heartbeats
4. **Agent Registry**:
- Bulk enable/disable LEITL for all agents
- Query LEITL status across the agent ecosystem
- Centralized session management
**Testing:**
- ✅ All Python files compile successfully
- ✅ Orchestration engine imports correctly
- ✅ BaseAgent with LEITL integration works
- ✅ AgentRegistry with LEITL support works
- ✅ Cece agent imports and executes
# Pull Request
## Description
<!-- Provide a brief description of the changes in this PR -->
## Type of Change
<!-- Mark the relevant option with an 'x' -->
- [ ] 📝 Documentation update
- [ ] 🧪 Tests only
- [ ] 🏗️ Scaffolding/stubs
- [ ] ✨ New feature
- [ ] 🐛 Bug fix
- [ ] ♻️ Refactoring
- [ ] ⚙️ Infrastructure/CI
- [ ] 📦 Dependencies update
- [ ] 🔒 Security fix
- [ ] 💥 Breaking change
## Checklist
<!-- Mark completed items with an 'x' -->
- [ ] Code follows the project's style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
## Auto-Merge Eligibility
<!-- This section helps determine if this PR qualifies for auto-merge
-->
**Eligible for auto-merge?**
- [ ] Yes - This is a docs-only, tests-only, or small AI-generated PR
- [ ] No - Requires human review
**Reason for auto-merge eligibility:**
- [ ] Docs-only (Tier 1)
- [ ] Tests-only (Tier 2)
- [ ] Scaffolding < 200 lines (Tier 3)
- [ ] AI-generated < 500 lines (Tier 4)
- [ ] Dependency patch/minor (Tier 5)
**If not auto-merge eligible, why?**
- [ ] Breaking change
- [ ] Security-related
- [ ] Infrastructure changes
- [ ] Requires discussion
- [ ] Large PR (> 500 lines)
## Related Issues
<!-- Link to related issues -->
Closes #
Related to #
## Test Plan
<!-- Describe how you tested these changes -->
## Screenshots (if applicable)
<!-- Add screenshots for UI changes -->
---
**Note**: This PR will be automatically labeled based on files changed.
See `GITHUB_AUTOMATION_RULES.md` for details.
If this PR meets auto-merge criteria (see `AUTO_MERGE_POLICY.md`), it
will be automatically approved and merged after checks pass.
For questions about the merge queue system, see `MERGE_QUEUE_PLAN.md`.
This commit is contained in:
@@ -3,6 +3,10 @@ Base Agent Class
|
|||||||
|
|
||||||
The foundation for all BlackRoad agents. Provides common functionality,
|
The foundation for all BlackRoad agents. Provides common functionality,
|
||||||
error handling, logging, and execution framework.
|
error handling, logging, and execution framework.
|
||||||
|
|
||||||
|
Integrations:
|
||||||
|
- LEITL Protocol: Multi-agent collaboration with live session management
|
||||||
|
- Cognition Framework: Access to Cece's reasoning and architecture capabilities
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -109,6 +113,11 @@ class BaseAgent(ABC):
|
|||||||
'on_success': []
|
'on_success': []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# LEITL Protocol integration (optional)
|
||||||
|
self._leitl_enabled: bool = False
|
||||||
|
self._leitl_session_id: Optional[str] = None
|
||||||
|
self._leitl_protocol = None # Will be set if LEITL is enabled
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
@@ -171,6 +180,16 @@ class BaseAgent(ABC):
|
|||||||
f"(ID: {execution_id})"
|
f"(ID: {execution_id})"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Broadcast task started via LEITL (if enabled)
|
||||||
|
await self._leitl_broadcast(
|
||||||
|
"task.started",
|
||||||
|
{
|
||||||
|
"task_id": execution_id,
|
||||||
|
"agent": self.metadata.name,
|
||||||
|
"description": str(params.get("input", ""))[:200]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate params
|
# Validate params
|
||||||
if not self.validate_params(params):
|
if not self.validate_params(params):
|
||||||
@@ -184,6 +203,10 @@ class BaseAgent(ABC):
|
|||||||
|
|
||||||
# Execute with retries
|
# Execute with retries
|
||||||
self.status = AgentStatus.RUNNING
|
self.status = AgentStatus.RUNNING
|
||||||
|
|
||||||
|
# Send heartbeat
|
||||||
|
await self._leitl_heartbeat(f"Executing {self.metadata.name}")
|
||||||
|
|
||||||
result_data = await self._execute_with_retry(params)
|
result_data = await self._execute_with_retry(params)
|
||||||
|
|
||||||
# Run success hooks
|
# Run success hooks
|
||||||
@@ -204,6 +227,17 @@ class BaseAgent(ABC):
|
|||||||
f"(Duration: {duration:.2f}s)"
|
f"(Duration: {duration:.2f}s)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Broadcast task completed via LEITL (if enabled)
|
||||||
|
await self._leitl_broadcast(
|
||||||
|
"task.completed",
|
||||||
|
{
|
||||||
|
"task_id": execution_id,
|
||||||
|
"agent": self.metadata.name,
|
||||||
|
"duration": duration,
|
||||||
|
"status": "success"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return AgentResult(
|
return AgentResult(
|
||||||
agent_name=self.metadata.name,
|
agent_name=self.metadata.name,
|
||||||
execution_id=execution_id,
|
execution_id=execution_id,
|
||||||
@@ -225,6 +259,17 @@ class BaseAgent(ABC):
|
|||||||
# Run error hooks
|
# Run error hooks
|
||||||
await self._run_hooks('on_error', {'error': str(e)})
|
await self._run_hooks('on_error', {'error': str(e)})
|
||||||
|
|
||||||
|
# Broadcast task failed via LEITL (if enabled)
|
||||||
|
await self._leitl_broadcast(
|
||||||
|
"task.failed",
|
||||||
|
{
|
||||||
|
"task_id": execution_id,
|
||||||
|
"agent": self.metadata.name,
|
||||||
|
"error": str(e),
|
||||||
|
"duration": duration
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return AgentResult(
|
return AgentResult(
|
||||||
agent_name=self.metadata.name,
|
agent_name=self.metadata.name,
|
||||||
execution_id=execution_id,
|
execution_id=execution_id,
|
||||||
@@ -311,5 +356,101 @@ class BaseAgent(ABC):
|
|||||||
'author': self.metadata.author,
|
'author': self.metadata.author,
|
||||||
'tags': self.metadata.tags,
|
'tags': self.metadata.tags,
|
||||||
'status': self.status.value,
|
'status': self.status.value,
|
||||||
'dependencies': self.metadata.dependencies
|
'dependencies': self.metadata.dependencies,
|
||||||
|
'leitl_enabled': self._leitl_enabled,
|
||||||
|
'leitl_session_id': self._leitl_session_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def enable_leitl(
|
||||||
|
self,
|
||||||
|
leitl_protocol=None,
|
||||||
|
tags: Optional[List[str]] = None
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Enable LEITL protocol for this agent
|
||||||
|
|
||||||
|
Args:
|
||||||
|
leitl_protocol: LEITL protocol instance (optional, will be imported if not provided)
|
||||||
|
tags: Optional tags for session categorization
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
LEITL session ID
|
||||||
|
"""
|
||||||
|
if self._leitl_enabled:
|
||||||
|
return self._leitl_session_id
|
||||||
|
|
||||||
|
# Import LEITL protocol if not provided
|
||||||
|
if leitl_protocol is None:
|
||||||
|
try:
|
||||||
|
from app.services.leitl_protocol import leitl_protocol as protocol
|
||||||
|
self._leitl_protocol = protocol
|
||||||
|
except ImportError:
|
||||||
|
self.logger.warning("LEITL protocol not available - running in standalone mode")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
self._leitl_protocol = leitl_protocol
|
||||||
|
|
||||||
|
# Register session
|
||||||
|
try:
|
||||||
|
session = await self._leitl_protocol.register_session(
|
||||||
|
agent_name=self.metadata.name,
|
||||||
|
agent_type=self.metadata.category,
|
||||||
|
tags=tags or self.metadata.tags
|
||||||
|
)
|
||||||
|
|
||||||
|
self._leitl_enabled = True
|
||||||
|
self._leitl_session_id = session.session_id
|
||||||
|
|
||||||
|
self.logger.info(f"✅ LEITL enabled - Session ID: {session.session_id}")
|
||||||
|
return session.session_id
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Failed to enable LEITL: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def disable_leitl(self):
|
||||||
|
"""Disable LEITL protocol and end session"""
|
||||||
|
if not self._leitl_enabled:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._leitl_protocol and self._leitl_session_id:
|
||||||
|
await self._leitl_protocol.end_session(self._leitl_session_id)
|
||||||
|
|
||||||
|
self._leitl_enabled = False
|
||||||
|
self._leitl_session_id = None
|
||||||
|
self.logger.info("LEITL session ended")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Error disabling LEITL: {str(e)}")
|
||||||
|
|
||||||
|
async def _leitl_broadcast(
|
||||||
|
self,
|
||||||
|
event_type: str,
|
||||||
|
data: Optional[Dict[str, Any]] = None
|
||||||
|
):
|
||||||
|
"""Broadcast event via LEITL protocol"""
|
||||||
|
if not self._leitl_enabled or not self._leitl_protocol:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._leitl_protocol.broadcast_event(
|
||||||
|
event_type=event_type,
|
||||||
|
session_id=self._leitl_session_id,
|
||||||
|
data=data
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"LEITL broadcast failed: {str(e)}")
|
||||||
|
|
||||||
|
async def _leitl_heartbeat(self, current_task: Optional[str] = None):
|
||||||
|
"""Send heartbeat to LEITL protocol"""
|
||||||
|
if not self._leitl_enabled or not self._leitl_protocol:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._leitl_protocol.heartbeat(
|
||||||
|
session_id=self._leitl_session_id,
|
||||||
|
current_task=current_task
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"LEITL heartbeat failed: {str(e)}")
|
||||||
|
|||||||
@@ -321,3 +321,80 @@ class AgentRegistry:
|
|||||||
'categories': self.list_categories(),
|
'categories': self.list_categories(),
|
||||||
'stats': self.get_stats()
|
'stats': self.get_stats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def enable_leitl_for_all(
|
||||||
|
self,
|
||||||
|
leitl_protocol=None,
|
||||||
|
tags: Optional[List[str]] = None
|
||||||
|
) -> Dict[str, str]:
|
||||||
|
"""
|
||||||
|
Enable LEITL protocol for all registered agents
|
||||||
|
|
||||||
|
This allows all agents to participate in the Live Everyone In The Loop
|
||||||
|
multi-agent collaboration protocol.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
leitl_protocol: LEITL protocol instance (optional, will be imported if not provided)
|
||||||
|
tags: Optional tags for sessions
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict mapping agent names to LEITL session IDs
|
||||||
|
"""
|
||||||
|
self.logger.info("🔗 Enabling LEITL for all agents...")
|
||||||
|
|
||||||
|
sessions = {}
|
||||||
|
|
||||||
|
for agent_name, agent in self._agents.items():
|
||||||
|
try:
|
||||||
|
session_id = await agent.enable_leitl(
|
||||||
|
leitl_protocol=leitl_protocol,
|
||||||
|
tags=tags
|
||||||
|
)
|
||||||
|
|
||||||
|
if session_id:
|
||||||
|
sessions[agent_name] = session_id
|
||||||
|
self.logger.info(f" ✓ {agent_name}: {session_id}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f" ✗ {agent_name}: {str(e)}")
|
||||||
|
|
||||||
|
self.logger.info(f"✅ LEITL enabled for {len(sessions)}/{len(self._agents)} agents")
|
||||||
|
|
||||||
|
return sessions
|
||||||
|
|
||||||
|
async def disable_leitl_for_all(self):
|
||||||
|
"""Disable LEITL protocol for all agents"""
|
||||||
|
self.logger.info("🔌 Disabling LEITL for all agents...")
|
||||||
|
|
||||||
|
for agent_name, agent in self._agents.items():
|
||||||
|
try:
|
||||||
|
await agent.disable_leitl()
|
||||||
|
self.logger.debug(f" ✓ {agent_name}")
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f" ✗ {agent_name}: {str(e)}")
|
||||||
|
|
||||||
|
self.logger.info("✅ LEITL disabled for all agents")
|
||||||
|
|
||||||
|
def get_leitl_status(self) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Get LEITL status for all agents
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict with LEITL enabled counts and session IDs
|
||||||
|
"""
|
||||||
|
enabled_agents = {}
|
||||||
|
disabled_agents = []
|
||||||
|
|
||||||
|
for agent_name, agent in self._agents.items():
|
||||||
|
if agent._leitl_enabled:
|
||||||
|
enabled_agents[agent_name] = agent._leitl_session_id
|
||||||
|
else:
|
||||||
|
disabled_agents.append(agent_name)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"leitl_enabled_count": len(enabled_agents),
|
||||||
|
"leitl_disabled_count": len(disabled_agents),
|
||||||
|
"enabled_agents": enabled_agents,
|
||||||
|
"disabled_agents": disabled_agents,
|
||||||
|
"total_agents": len(self._agents)
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from app.routers import (
|
|||||||
digitalocean, github, huggingface, vscode, games, browser, dashboard,
|
digitalocean, github, huggingface, vscode, games, browser, dashboard,
|
||||||
railway, vercel, stripe, twilio, slack, discord, sentry, api_health, agents,
|
railway, vercel, stripe, twilio, slack, discord, sentry, api_health, agents,
|
||||||
capture, identity_center, notifications_center, creator, compliance_ops,
|
capture, identity_center, notifications_center, creator, compliance_ops,
|
||||||
search, cloudflare, system, webhooks, prism_static, ip_vault, leitl
|
search, cloudflare, system, webhooks, prism_static, ip_vault, leitl, cognition
|
||||||
)
|
)
|
||||||
from app.services.crypto import rotate_plaintext_wallet_keys
|
from app.services.crypto import rotate_plaintext_wallet_keys
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ openapi_tags = [
|
|||||||
{"name": "cloudflare", "description": "Cloudflare zone, DNS, and Worker scaffolding"},
|
{"name": "cloudflare", "description": "Cloudflare zone, DNS, and Worker scaffolding"},
|
||||||
{"name": "IP Vault", "description": "Cryptographic proof-of-origin for ideas and intellectual property"},
|
{"name": "IP Vault", "description": "Cryptographic proof-of-origin for ideas and intellectual property"},
|
||||||
{"name": "LEITL", "description": "Live Everyone In The Loop - Multi-agent collaboration with WebDAV context"},
|
{"name": "LEITL", "description": "Live Everyone In The Loop - Multi-agent collaboration with WebDAV context"},
|
||||||
|
{"name": "Cognition", "description": "Cece Cognition Framework - 15-step reasoning + 6-step architecture + multi-agent orchestration"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -165,6 +166,9 @@ app.include_router(ip_vault.router)
|
|||||||
# LEITL Protocol - Live Everyone In The Loop
|
# LEITL Protocol - Live Everyone In The Loop
|
||||||
app.include_router(leitl.router)
|
app.include_router(leitl.router)
|
||||||
|
|
||||||
|
# Cognition Framework - Cece + Multi-Agent Orchestration
|
||||||
|
app.include_router(cognition.router)
|
||||||
|
|
||||||
# GitHub Webhooks (Phase Q automation)
|
# GitHub Webhooks (Phase Q automation)
|
||||||
app.include_router(webhooks.router)
|
app.include_router(webhooks.router)
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from agents.categories.ai_ml.cece_agent import CeceAgent
|
|||||||
from agents.categories.ai_ml.wasp_agent import WaspAgent
|
from agents.categories.ai_ml.wasp_agent import WaspAgent
|
||||||
from agents.categories.ai_ml.clause_agent import ClauseAgent
|
from agents.categories.ai_ml.clause_agent import ClauseAgent
|
||||||
from agents.categories.ai_ml.codex_agent import CodexAgent
|
from agents.categories.ai_ml.codex_agent import CodexAgent
|
||||||
from backend.app.services.orchestration import (
|
from app.services.orchestration import (
|
||||||
OrchestrationEngine,
|
OrchestrationEngine,
|
||||||
Workflow,
|
Workflow,
|
||||||
WorkflowStep,
|
WorkflowStep,
|
||||||
|
|||||||
Reference in New Issue
Block a user