aboutsummaryrefslogtreecommitdiff
path: root/agent/orchestrator/models/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'agent/orchestrator/models/base.py')
-rw-r--r--agent/orchestrator/models/base.py44
1 files changed, 44 insertions, 0 deletions
diff --git a/agent/orchestrator/models/base.py b/agent/orchestrator/models/base.py
new file mode 100644
index 0000000..4ca1988
--- /dev/null
+++ b/agent/orchestrator/models/base.py
@@ -0,0 +1,44 @@
+"""Backend-agnostic model interface.
+
+Concrete backends (Claude Code, Ollama, Anthropic API direct, OpenCode, etc.)
+implement `ModelBackend.call`. The orchestration code only ever talks to this
+interface, never to a specific backend.
+
+Persona is NOT carried in ModelRequest; that's a backend-level configuration
+concern (some backends autodiscover persona from a workspace, others need to
+be told). What flows through here is per-turn DYNAMIC context only.
+"""
+
+from abc import ABC, abstractmethod
+from dataclasses import dataclass, field
+from typing import Literal
+
+
+Role = Literal["system", "user", "assistant", "tool"]
+
+
+@dataclass
+class Message:
+ role: Role
+ content: str
+
+
+@dataclass
+class ModelRequest:
+ """Everything a backend needs to produce one response."""
+ messages: list[Message]
+ turn_context: str | None = None
+ extras: dict = field(default_factory=dict)
+
+
+@dataclass
+class ModelResponse:
+ """What a backend returns. Kept narrow now, extended later."""
+ content: str
+ extras: dict = field(default_factory=dict)
+
+
+class ModelBackend(ABC):
+ @abstractmethod
+ def call(self, request: ModelRequest) -> ModelResponse:
+ ...