PlanOpticon

planopticon / docs / api / agent.md
Source Blame History 407 lines
3551b80… noreply 1 # Agent API Reference
3551b80… noreply 2
3551b80… noreply 3 ::: video_processor.agent.agent_loop
3551b80… noreply 4
3551b80… noreply 5 ::: video_processor.agent.skills.base
3551b80… noreply 6
3551b80… noreply 7 ::: video_processor.agent.kb_context
3551b80… noreply 8
3551b80… noreply 9 ---
3551b80… noreply 10
3551b80… noreply 11 ## Overview
3551b80… noreply 12
3551b80… noreply 13 The agent module implements a planning agent that synthesizes knowledge from processed video content into actionable artifacts such as project plans, PRDs, task breakdowns, and roadmaps. The agent operates on knowledge graphs loaded via `KBContext` and uses a skill-based architecture for extensibility.
3551b80… noreply 14
3551b80… noreply 15 **Key components:**
3551b80… noreply 16
3551b80… noreply 17 - **`PlanningAgent`** -- orchestrates skill selection and execution based on user requests
3551b80… noreply 18 - **`AgentContext`** -- shared state passed between skills during execution
3551b80… noreply 19 - **`Skill`** (ABC) -- base class for pluggable agent capabilities
3551b80… noreply 20 - **`Artifact`** -- output produced by skill execution
3551b80… noreply 21 - **`KBContext`** -- loads and merges multiple knowledge graph sources
3551b80… noreply 22
3551b80… noreply 23 ---
3551b80… noreply 24
3551b80… noreply 25 ## PlanningAgent
3551b80… noreply 26
3551b80… noreply 27 ```python
3551b80… noreply 28 from video_processor.agent.agent_loop import PlanningAgent
3551b80… noreply 29 ```
3551b80… noreply 30
3551b80… noreply 31 AI agent that synthesizes knowledge into planning artifacts. Uses an LLM to select which skills to execute for a given request, or falls back to keyword matching when no LLM is available.
3551b80… noreply 32
3551b80… noreply 33 ### Constructor
3551b80… noreply 34
3551b80… noreply 35 ```python
3551b80… noreply 36 def __init__(self, context: AgentContext)
3551b80… noreply 37 ```
3551b80… noreply 38
3551b80… noreply 39 | Parameter | Type | Description |
3551b80… noreply 40 |---|---|---|
3551b80… noreply 41 | `context` | `AgentContext` | Shared context containing knowledge graph, query engine, and provider |
3551b80… noreply 42
3551b80… noreply 43 ### from_kb_paths()
3551b80… noreply 44
3551b80… noreply 45 ```python
3551b80… noreply 46 @classmethod
3551b80… noreply 47 def from_kb_paths(
3551b80… noreply 48 cls,
3551b80… noreply 49 kb_paths: List[Path],
3551b80… noreply 50 provider_manager=None,
3551b80… noreply 51 ) -> PlanningAgent
3551b80… noreply 52 ```
3551b80… noreply 53
3551b80… noreply 54 Factory method that creates an agent from one or more knowledge base file paths. Handles loading and merging knowledge graphs automatically.
3551b80… noreply 55
3551b80… noreply 56 **Parameters:**
3551b80… noreply 57
3551b80… noreply 58 | Parameter | Type | Default | Description |
3551b80… noreply 59 |---|---|---|---|
3551b80… noreply 60 | `kb_paths` | `List[Path]` | *required* | Paths to `.db` or `.json` knowledge graph files, or directories to search |
3551b80… noreply 61 | `provider_manager` | `ProviderManager` | `None` | LLM provider for agent operations |
3551b80… noreply 62
3551b80… noreply 63 **Returns:** `PlanningAgent` -- configured agent with loaded knowledge base.
3551b80… noreply 64
3551b80… noreply 65 ```python
3551b80… noreply 66 from pathlib import Path
3551b80… noreply 67 from video_processor.agent.agent_loop import PlanningAgent
3551b80… noreply 68 from video_processor.providers.manager import ProviderManager
3551b80… noreply 69
3551b80… noreply 70 agent = PlanningAgent.from_kb_paths(
3551b80… noreply 71 kb_paths=[Path("results/knowledge_graph.db")],
3551b80… noreply 72 provider_manager=ProviderManager(),
3551b80… noreply 73 )
3551b80… noreply 74 ```
3551b80… noreply 75
3551b80… noreply 76 ### execute()
3551b80… noreply 77
3551b80… noreply 78 ```python
3551b80… noreply 79 def execute(self, request: str) -> List[Artifact]
3551b80… noreply 80 ```
3551b80… noreply 81
3551b80… noreply 82 Execute a user request by selecting and running appropriate skills.
3551b80… noreply 83
3551b80… noreply 84 **Process:**
3551b80… noreply 85
3551b80… noreply 86 1. Build a context summary from the knowledge base statistics
3551b80… noreply 87 2. Format available skills with their descriptions
3551b80… noreply 88 3. Ask the LLM to select skills and parameters (or use keyword matching as fallback)
3551b80… noreply 89 4. Execute selected skills in order, accumulating artifacts
3551b80… noreply 90
3551b80… noreply 91 **Parameters:**
3551b80… noreply 92
3551b80… noreply 93 | Parameter | Type | Description |
3551b80… noreply 94 |---|---|---|
3551b80… noreply 95 | `request` | `str` | Natural language request (e.g., "Generate a project plan") |
3551b80… noreply 96
3551b80… noreply 97 **Returns:** `List[Artifact]` -- generated artifacts from skill execution.
3551b80… noreply 98
3551b80… noreply 99 **LLM mode:** The LLM receives the knowledge base summary, available skills, and user request, then returns a JSON array of `{"skill": "name", "params": {}}` objects to execute.
3551b80… noreply 100
3551b80… noreply 101 **Keyword fallback:** Without an LLM, skills are matched by splitting the skill name into words and checking if any appear in the request text.
3551b80… noreply 102
3551b80… noreply 103 ```python
3551b80… noreply 104 artifacts = agent.execute("Create a PRD and task breakdown")
3551b80… noreply 105 for artifact in artifacts:
3551b80… noreply 106 print(f"--- {artifact.name} ({artifact.artifact_type}) ---")
3551b80… noreply 107 print(artifact.content[:500])
3551b80… noreply 108 ```
3551b80… noreply 109
3551b80… noreply 110 ### chat()
3551b80… noreply 111
3551b80… noreply 112 ```python
3551b80… noreply 113 def chat(self, message: str) -> str
3551b80… noreply 114 ```
3551b80… noreply 115
3551b80… noreply 116 Interactive chat mode. Maintains conversation history and provides contextual responses about the loaded knowledge base.
3551b80… noreply 117
3551b80… noreply 118 **Parameters:**
3551b80… noreply 119
3551b80… noreply 120 | Parameter | Type | Description |
3551b80… noreply 121 |---|---|---|
3551b80… noreply 122 | `message` | `str` | User message |
3551b80… noreply 123
3551b80… noreply 124 **Returns:** `str` -- assistant response.
3551b80… noreply 125
3551b80… noreply 126 The chat mode provides the LLM with:
3551b80… noreply 127
3551b80… noreply 128 - Knowledge base statistics (entity counts, relationship counts)
3551b80… noreply 129 - List of previously generated artifacts
3551b80… noreply 130 - Full conversation history
3551b80… noreply 131 - Available REPL commands (e.g., `/entities`, `/search`, `/plan`, `/export`)
3551b80… noreply 132
3551b80… noreply 133 **Requires** a configured `provider_manager`. Returns a static error message if no LLM is available.
3551b80… noreply 134
3551b80… noreply 135 ```python
3551b80… noreply 136 response = agent.chat("What technologies were discussed in the meetings?")
3551b80… noreply 137 print(response)
3551b80… noreply 138
3551b80… noreply 139 response = agent.chat("Which of those have the most dependencies?")
3551b80… noreply 140 print(response)
3551b80… noreply 141 ```
3551b80… noreply 142
3551b80… noreply 143 ---
3551b80… noreply 144
3551b80… noreply 145 ## AgentContext
3551b80… noreply 146
3551b80… noreply 147 ```python
3551b80… noreply 148 from video_processor.agent.skills.base import AgentContext
3551b80… noreply 149 ```
3551b80… noreply 150
3551b80… noreply 151 Shared state dataclass passed to all skills during execution. Accumulates artifacts and conversation history across the agent session.
3551b80… noreply 152
3551b80… noreply 153 | Field | Type | Default | Description |
3551b80… noreply 154 |---|---|---|---|
3551b80… noreply 155 | `knowledge_graph` | `Any` | `None` | `KnowledgeGraph` instance |
3551b80… noreply 156 | `query_engine` | `Any` | `None` | `GraphQueryEngine` instance for querying the KG |
3551b80… noreply 157 | `provider_manager` | `Any` | `None` | `ProviderManager` instance for LLM calls |
3551b80… noreply 158 | `planning_entities` | `List[Any]` | `[]` | Extracted `PlanningEntity` instances |
3551b80… noreply 159 | `user_requirements` | `Dict[str, Any]` | `{}` | User-specified requirements and constraints |
3551b80… noreply 160 | `conversation_history` | `List[Dict[str, str]]` | `[]` | Chat message history (`role`, `content` dicts) |
3551b80… noreply 161 | `artifacts` | `List[Artifact]` | `[]` | Previously generated artifacts |
3551b80… noreply 162 | `config` | `Dict[str, Any]` | `{}` | Additional configuration |
3551b80… noreply 163
3551b80… noreply 164 ```python
3551b80… noreply 165 from video_processor.agent.skills.base import AgentContext
3551b80… noreply 166
3551b80… noreply 167 context = AgentContext(
3551b80… noreply 168 knowledge_graph=kg,
3551b80… noreply 169 query_engine=engine,
3551b80… noreply 170 provider_manager=pm,
3551b80… noreply 171 config={"output_format": "markdown"},
3551b80… noreply 172 )
3551b80… noreply 173 ```
3551b80… noreply 174
3551b80… noreply 175 ---
3551b80… noreply 176
3551b80… noreply 177 ## Skill (ABC)
3551b80… noreply 178
3551b80… noreply 179 ```python
3551b80… noreply 180 from video_processor.agent.skills.base import Skill
3551b80… noreply 181 ```
3551b80… noreply 182
3551b80… noreply 183 Base class for agent skills. Each skill represents a discrete capability that produces an artifact from the agent context.
3551b80… noreply 184
3551b80… noreply 185 **Class attributes:**
3551b80… noreply 186
3551b80… noreply 187 | Attribute | Type | Description |
3551b80… noreply 188 |---|---|---|
3551b80… noreply 189 | `name` | `str` | Skill identifier (e.g., `"project_plan"`, `"prd"`) |
3551b80… noreply 190 | `description` | `str` | Human-readable description shown to the LLM for skill selection |
3551b80… noreply 191
3551b80… noreply 192 ### execute()
3551b80… noreply 193
3551b80… noreply 194 ```python
3551b80… noreply 195 @abstractmethod
3551b80… noreply 196 def execute(self, context: AgentContext, **kwargs) -> Artifact
3551b80… noreply 197 ```
3551b80… noreply 198
3551b80… noreply 199 Execute this skill and return an artifact. Receives the shared agent context and any parameters selected by the LLM planner.
3551b80… noreply 200
3551b80… noreply 201 ### can_execute()
3551b80… noreply 202
3551b80… noreply 203 ```python
3551b80… noreply 204 def can_execute(self, context: AgentContext) -> bool
3551b80… noreply 205 ```
3551b80… noreply 206
3551b80… noreply 207 Check if this skill can execute given the current context. The default implementation requires both `knowledge_graph` and `provider_manager` to be set. Override for skills with different requirements.
3551b80… noreply 208
3551b80… noreply 209 **Returns:** `bool`
3551b80… noreply 210
3551b80… noreply 211 ### Implementing a custom skill
3551b80… noreply 212
3551b80… noreply 213 ```python
3551b80… noreply 214 from video_processor.agent.skills.base import Skill, Artifact, AgentContext, register_skill
3551b80… noreply 215
3551b80… noreply 216 class SummarySkill(Skill):
3551b80… noreply 217 name = "summary"
3551b80… noreply 218 description = "Generate a concise summary of the knowledge base"
3551b80… noreply 219
3551b80… noreply 220 def execute(self, context: AgentContext, **kwargs) -> Artifact:
3551b80… noreply 221 stats = context.query_engine.stats()
3551b80… noreply 222 prompt = f"Summarize this knowledge base:\n{stats.to_text()}"
3551b80… noreply 223 content = context.provider_manager.chat(
3551b80… noreply 224 [{"role": "user", "content": prompt}]
3551b80… noreply 225 )
3551b80… noreply 226 return Artifact(
3551b80… noreply 227 name="Knowledge Base Summary",
3551b80… noreply 228 content=content,
3551b80… noreply 229 artifact_type="document",
3551b80… noreply 230 format="markdown",
3551b80… noreply 231 )
3551b80… noreply 232
3551b80… noreply 233 def can_execute(self, context: AgentContext) -> bool:
3551b80… noreply 234 return context.query_engine is not None and context.provider_manager is not None
3551b80… noreply 235
3551b80… noreply 236 # Register the skill so the agent can discover it
3551b80… noreply 237 register_skill(SummarySkill())
3551b80… noreply 238 ```
3551b80… noreply 239
3551b80… noreply 240 ---
3551b80… noreply 241
3551b80… noreply 242 ## Artifact
3551b80… noreply 243
3551b80… noreply 244 ```python
3551b80… noreply 245 from video_processor.agent.skills.base import Artifact
3551b80… noreply 246 ```
3551b80… noreply 247
3551b80… noreply 248 Dataclass representing the output of a skill execution.
3551b80… noreply 249
3551b80… noreply 250 | Field | Type | Default | Description |
3551b80… noreply 251 |---|---|---|---|
3551b80… noreply 252 | `name` | `str` | *required* | Human-readable artifact name |
3551b80… noreply 253 | `content` | `str` | *required* | Generated content (Markdown, JSON, Mermaid, etc.) |
3551b80… noreply 254 | `artifact_type` | `str` | *required* | Type: `"project_plan"`, `"prd"`, `"roadmap"`, `"task_list"`, `"document"`, `"issues"` |
3551b80… noreply 255 | `format` | `str` | `"markdown"` | Content format: `"markdown"`, `"json"`, `"mermaid"` |
3551b80… noreply 256 | `metadata` | `Dict[str, Any]` | `{}` | Additional metadata |
3551b80… noreply 257
3551b80… noreply 258 ---
3551b80… noreply 259
3551b80… noreply 260 ## Skill Registry Functions
3551b80… noreply 261
3551b80… noreply 262 ### register_skill()
3551b80… noreply 263
3551b80… noreply 264 ```python
3551b80… noreply 265 def register_skill(skill: Skill) -> None
3551b80… noreply 266 ```
3551b80… noreply 267
3551b80… noreply 268 Register a skill instance in the global registry. Skills must be registered before the agent can discover and execute them.
3551b80… noreply 269
3551b80… noreply 270 ### get_skill()
3551b80… noreply 271
3551b80… noreply 272 ```python
3551b80… noreply 273 def get_skill(name: str) -> Optional[Skill]
3551b80… noreply 274 ```
3551b80… noreply 275
3551b80… noreply 276 Look up a registered skill by name.
3551b80… noreply 277
3551b80… noreply 278 **Returns:** `Optional[Skill]` -- the skill instance, or `None` if not found.
3551b80… noreply 279
3551b80… noreply 280 ### list_skills()
3551b80… noreply 281
3551b80… noreply 282 ```python
3551b80… noreply 283 def list_skills() -> List[Skill]
3551b80… noreply 284 ```
3551b80… noreply 285
3551b80… noreply 286 Return all registered skill instances.
3551b80… noreply 287
3551b80… noreply 288 ---
3551b80… noreply 289
3551b80… noreply 290 ## KBContext
3551b80… noreply 291
3551b80… noreply 292 ```python
3551b80… noreply 293 from video_processor.agent.kb_context import KBContext
3551b80… noreply 294 ```
3551b80… noreply 295
3551b80… noreply 296 Loads and merges multiple knowledge graph sources into a unified context for agent consumption. Supports both FalkorDB (`.db`) and JSON (`.json`) formats, and can auto-discover graphs in a directory tree.
3551b80… noreply 297
3551b80… noreply 298 ### Constructor
3551b80… noreply 299
3551b80… noreply 300 ```python
3551b80… noreply 301 def __init__(self)
3551b80… noreply 302 ```
3551b80… noreply 303
3551b80… noreply 304 Creates an empty context. Use `add_source()` to add knowledge graph paths, then `load()` to initialize.
3551b80… noreply 305
3551b80… noreply 306 ### add_source()
3551b80… noreply 307
3551b80… noreply 308 ```python
3551b80… noreply 309 def add_source(self, path) -> None
3551b80… noreply 310 ```
3551b80… noreply 311
3551b80… noreply 312 Add a knowledge graph source.
3551b80… noreply 313
3551b80… noreply 314 **Parameters:**
3551b80… noreply 315
3551b80… noreply 316 | Parameter | Type | Description |
3551b80… noreply 317 |---|---|---|
3551b80… noreply 318 | `path` | `str \| Path` | Path to a `.db` file, `.json` file, or directory to search for knowledge graphs |
3551b80… noreply 319
3551b80… noreply 320 If `path` is a directory, it is searched recursively for knowledge graph files using `find_knowledge_graphs()`.
3551b80… noreply 321
3551b80… noreply 322 **Raises:** `FileNotFoundError` if the path does not exist.
3551b80… noreply 323
3551b80… noreply 324 ### load()
3551b80… noreply 325
3551b80… noreply 326 ```python
3551b80… noreply 327 def load(self, provider_manager=None) -> KBContext
3551b80… noreply 328 ```
3551b80… noreply 329
3551b80… noreply 330 Load and merge all added sources into a single knowledge graph and query engine.
3551b80… noreply 331
3551b80… noreply 332 **Parameters:**
3551b80… noreply 333
3551b80… noreply 334 | Parameter | Type | Default | Description |
3551b80… noreply 335 |---|---|---|---|
3551b80… noreply 336 | `provider_manager` | `ProviderManager` | `None` | LLM provider for the knowledge graph and query engine |
3551b80… noreply 337
3551b80… noreply 338 **Returns:** `KBContext` -- self, for method chaining.
3551b80… noreply 339
3551b80… noreply 340 ### Properties
3551b80… noreply 341
3551b80… noreply 342 | Property | Type | Description |
3551b80… noreply 343 |---|---|---|
3551b80… noreply 344 | `knowledge_graph` | `KnowledgeGraph` | The merged knowledge graph (raises `RuntimeError` if not loaded) |
3551b80… noreply 345 | `query_engine` | `GraphQueryEngine` | Query engine for the merged graph (raises `RuntimeError` if not loaded) |
3551b80… noreply 346 | `sources` | `List[Path]` | List of resolved source paths |
3551b80… noreply 347
3551b80… noreply 348 ### summary()
3551b80… noreply 349
3551b80… noreply 350 ```python
3551b80… noreply 351 def summary(self) -> str
3551b80… noreply 352 ```
3551b80… noreply 353
3551b80… noreply 354 Generate a brief text summary of the loaded knowledge base, including entity counts by type and relationship counts.
3551b80… noreply 355
3551b80… noreply 356 **Returns:** `str` -- multi-line summary text.
3551b80… noreply 357
3551b80… noreply 358 ### auto_discover()
3551b80… noreply 359
3551b80… noreply 360 ```python
3551b80… noreply 361 @classmethod
3551b80… noreply 362 def auto_discover(
3551b80… noreply 363 cls,
3551b80… noreply 364 start_dir: Optional[Path] = None,
3551b80… noreply 365 provider_manager=None,
3551b80… noreply 366 ) -> KBContext
3551b80… noreply 367 ```
3551b80… noreply 368
3551b80… noreply 369 Factory method that creates a `KBContext` by auto-discovering knowledge graphs near `start_dir` (defaults to current directory).
3551b80… noreply 370
3551b80… noreply 371 **Returns:** `KBContext` -- loaded context (may have zero sources if none found).
3551b80… noreply 372
3551b80… noreply 373 ### Usage examples
3551b80… noreply 374
3551b80… noreply 375 ```python
3551b80… noreply 376 from pathlib import Path
3551b80… noreply 377 from video_processor.agent.kb_context import KBContext
3551b80… noreply 378
3551b80… noreply 379 # Manual source management
3551b80… noreply 380 kb = KBContext()
3551b80… noreply 381 kb.add_source(Path("project_a/knowledge_graph.db"))
3551b80… noreply 382 kb.add_source(Path("project_b/results/")) # searches directory
3551b80… noreply 383 kb.load(provider_manager=pm)
3551b80… noreply 384
3551b80… noreply 385 print(kb.summary())
3551b80… noreply 386 # Knowledge base: 3 source(s)
3551b80… noreply 387 # Entities: 142
3551b80… noreply 388 # Relationships: 89
3551b80… noreply 389 # Entity types:
3551b80… noreply 390 # technology: 45
3551b80… noreply 391 # person: 23
3551b80… noreply 392 # concept: 74
3551b80… noreply 393
3551b80… noreply 394 # Auto-discover from current directory
3551b80… noreply 395 kb = KBContext.auto_discover()
3551b80… noreply 396
3551b80… noreply 397 # Use with the agent
3551b80… noreply 398 from video_processor.agent.agent_loop import PlanningAgent
3551b80… noreply 399 from video_processor.agent.skills.base import AgentContext
3551b80… noreply 400
3551b80… noreply 401 context = AgentContext(
3551b80… noreply 402 knowledge_graph=kb.knowledge_graph,
3551b80… noreply 403 query_engine=kb.query_engine,
3551b80… noreply 404 provider_manager=pm,
3551b80… noreply 405 )
3551b80… noreply 406 agent = PlanningAgent(context)
3551b80… noreply 407 ```

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button