initial commit
This commit is contained in:
88
02-Architektura/Control Plane.md
Normal file
88
02-Architektura/Control Plane.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Control Plane
|
||||
|
||||
#sympozium #architektura #control-plane
|
||||
|
||||
## Komponenty
|
||||
|
||||
Control Plane Sympozium składa się z następujących komponentów:
|
||||
|
||||
### Controller Manager
|
||||
Serce systemu. Zawiera **6 [[Controller i Reconciler|reconcilerów]]** + 2 routery:
|
||||
|
||||
| Reconciler | CRD | Odpowiedzialność |
|
||||
|------------|-----|------------------|
|
||||
| `AgentRunReconciler` | AgentRun | Tworzy Job/Sandbox CR, monitoruje lifecycle, zbiera wyniki |
|
||||
| `SympoziumInstanceReconciler` | SympoziumInstance | Zarządza kanałami, memory, web endpoints |
|
||||
| `PersonaPackReconciler` | PersonaPack | Stampuje instancje, schedules, memory z packów |
|
||||
| `SkillPackReconciler` | SkillPack | Generuje ConfigMapy ze skilli |
|
||||
| `SympoziumPolicyReconciler` | SympoziumPolicy | Zarządza politykami |
|
||||
| `SympoziumScheduleReconciler` | SympoziumSchedule | Tworzy AgentRuns wg harmonogramu cron |
|
||||
| `MCPServerReconciler` | MCPServer | Deployuje i probeuje MCP serwery |
|
||||
|
||||
**Routery** (reagują na eventy NATS):
|
||||
- `ChannelRouter` - przetwarza wiadomości z kanałów → tworzy AgentRun
|
||||
- `ScheduleRouter` - obsługuje `schedule.upsert` z agentów → tworzy/aktualizuje SympoziumSchedule
|
||||
|
||||
### API Server
|
||||
- HTTP + WebSocket API
|
||||
- Serwuje embedded web UI (React)
|
||||
- Czyta annotacje node'ów (inference discovery)
|
||||
- Sesje i historia w PostgreSQL
|
||||
|
||||
### [[Admission Webhook]]
|
||||
- Enforces `SympoziumPolicy` przy tworzeniu AgentRun
|
||||
- Waliduje sandbox requirements, tool gating, feature gates
|
||||
- Działa at admission time, nie at runtime
|
||||
|
||||
### [[NATS JetStream]]
|
||||
- Durable pub/sub event bus
|
||||
- Decouples kanały od control plane
|
||||
- Replay capability dla niezawodności
|
||||
|
||||
## Warstwa danych
|
||||
|
||||
| Magazyn | Zastosowanie |
|
||||
|---------|-------------|
|
||||
| **etcd** | [[CRD - Custom Resource Definition|CRD]] state (via K8s API) |
|
||||
| **PostgreSQL** | Sesje, historia konwersacji |
|
||||
| **SQLite + FTS5** | Persistent memory agentów (na PVC) |
|
||||
| **[[ConfigMap i Secret\|ConfigMaps]]** | Skills, legacy memory |
|
||||
| **[[ConfigMap i Secret\|Secrets]]** | Klucze API providerów |
|
||||
|
||||
## Przepływ reconciliation
|
||||
|
||||
```
|
||||
User/Channel → Wiadomość
|
||||
↓
|
||||
Channel Pod → NATS (channel.message.received)
|
||||
↓
|
||||
Channel Router → Tworzy AgentRun CR
|
||||
↓
|
||||
AgentRun Reconciler:
|
||||
1. Walidacja polityki (SympoziumPolicy)
|
||||
2. Tworzenie input ConfigMap (task + system prompt)
|
||||
3. Rozwiązywanie skill sidecars (SkillPack CRDs)
|
||||
4. Rozwiązywanie MCP serverów
|
||||
5. Tworzenie Job/Sandbox CR z:
|
||||
- Agent container
|
||||
- IPC bridge sidecar
|
||||
- Skill sidecars (z auto-provisioned RBAC)
|
||||
- MCP bridge sidecar (opcjonalnie)
|
||||
- Sandbox sidecar (opcjonalnie)
|
||||
6. Monitorowanie faz: Pending → Running → Succeeded/Failed
|
||||
7. Zbieranie wyników z logów poda
|
||||
8. Ekstrakcja memory updates
|
||||
9. Czyszczenie RBAC i zasobów
|
||||
```
|
||||
|
||||
## Metryki OTel
|
||||
|
||||
Controller eksportuje metryki OpenTelemetry:
|
||||
- `sympozium.agent.runs` - counter zakończonych runów
|
||||
- `sympozium.agent.duration_ms` - histogram czasu trwania
|
||||
- `sympozium.errors` - counter błędów
|
||||
- `sympozium.web_endpoint.serving` - aktywne deployments server-mode
|
||||
|
||||
---
|
||||
|
||||
Powiązane: [[Cykl życia Agent Pod]] | [[NATS JetStream - Event Bus]] | [[Orchestrator - PodBuilder i Spawner]]
|
||||
114
02-Architektura/Cykl życia Agent Pod.md
Normal file
114
02-Architektura/Cykl życia Agent Pod.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Cykl życia Agent Pod
|
||||
|
||||
#sympozium #architektura #agent-pod
|
||||
|
||||
## Anatomia Agent Pod
|
||||
|
||||
Każdy agent run tworzy pod z następującymi kontenerami:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Agent Pod (Job) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
||||
│ │ Agent │ │ IPC Bridge │ │ Skill Sidecar│ │
|
||||
│ │ Container │ │ Sidecar │ │ (kubectl, │ │
|
||||
│ │ │ │ │ │ helm, etc.) │ │
|
||||
│ │ - LLM loop │ │ - fsnotify │ │ │ │
|
||||
│ │ - Tool exec │ │ - NATS pub │ │ - /workspace │ │
|
||||
│ │ - /skills │ │ - /ipc │ │ - RBAC scope │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
│ /workspace /ipc (tmpfs) /workspace │
|
||||
│ /skills (ro) (RAM-backed) │
|
||||
│ /ipc │
|
||||
│ /tmp │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ MCP Bridge │ │ Sandbox │ │
|
||||
│ │ (opcjonalny) │ │ (opcjonalny) │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Woluminy
|
||||
|
||||
| Wolumin | Typ | Rozmiar | Cel |
|
||||
|---------|-----|---------|-----|
|
||||
| `workspace` | emptyDir | 1Gi | Współdzielone pliki robocze agent ↔ sidecary |
|
||||
| `ipc` | emptyDir (RAM) | 64Mi | JSON IPC: agent → bridge → NATS |
|
||||
| `skills` | Projected ConfigMap | - | Markdown instrukcje ze SkillPacks (read-only) |
|
||||
| `tmp` | emptyDir | 256Mi | Tymczasowe pliki (read-only root FS) |
|
||||
|
||||
## [[SecurityContext]] agenta
|
||||
|
||||
Hardened security context - patrz [[SecurityContext]] dla wyjaśnienia poszczególnych pól:
|
||||
|
||||
```go
|
||||
SecurityContext: &corev1.SecurityContext{
|
||||
ReadOnlyRootFilesystem: &readOnly, // true - root FS read-only
|
||||
AllowPrivilegeEscalation: &noPrivEsc, // false - blokuje setuid
|
||||
Capabilities: &corev1.Capabilities{
|
||||
Drop: []corev1.Capability{"ALL"}, // Drop ALL Linux capabilities
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Zasoby
|
||||
|
||||
| Kontener | CPU Request | CPU Limit | Memory Request | Memory Limit |
|
||||
|----------|-------------|-----------|----------------|--------------|
|
||||
| Agent | 250m | 1 | 512Mi | 1Gi |
|
||||
| IPC Bridge | 50m | 100m | 64Mi | 128Mi |
|
||||
| Sandbox | 100m | 500m | 256Mi | 512Mi |
|
||||
|
||||
## Fazy lifecycle
|
||||
|
||||
```
|
||||
Pending → Running → Succeeded
|
||||
→ Failed
|
||||
→ Serving (tryb server)
|
||||
```
|
||||
|
||||
### Pending
|
||||
1. Walidacja polityki
|
||||
2. Tworzenie ServiceAccount `sympozium-agent`
|
||||
3. Tworzenie input ConfigMap (task, system prompt, memory)
|
||||
4. Rozwiązywanie sidecars i RBAC
|
||||
5. Tworzenie Job/Sandbox CR
|
||||
|
||||
### Running
|
||||
- Polling statusu poda co 10 sekund
|
||||
- Monitorowanie completion/failure
|
||||
|
||||
### Succeeded/Failed
|
||||
1. Zbieranie logów poda (wynik agenta)
|
||||
2. Ekstrakcja memory markers z outputu
|
||||
3. Aktualizacja memory ConfigMap
|
||||
4. Usuwanie efemerycznego RBAC
|
||||
5. Pruning historii (domyślnie 50 runów per instancja)
|
||||
6. Usuwanie finalizera
|
||||
|
||||
### Serving (tryb server)
|
||||
- Deployment zamiast Job
|
||||
- Service dla routowania
|
||||
- Używany dla web-endpoint
|
||||
- Długo żyjący, nie jest garbage-collectowany po zakończeniu
|
||||
|
||||
## Zmienne środowiskowe agenta
|
||||
|
||||
| Zmienna | Wartość |
|
||||
|---------|---------|
|
||||
| `AGENT_RUN_ID` | Nazwa AgentRun CR |
|
||||
| `AGENT_ID` | ID konfiguracji agenta |
|
||||
| `SESSION_KEY` | Klucz sesji |
|
||||
| `INSTANCE_NAME` | Nazwa SympoziumInstance |
|
||||
| `MODEL_PROVIDER` | openai/anthropic/azure/ollama |
|
||||
| `MODEL_NAME` | Identyfikator modelu |
|
||||
| `THINKING_MODE` | off/low/medium/high |
|
||||
| `SPAWN_DEPTH` | Głębokość zagnieżdżenia sub-agenta |
|
||||
| `TRACEPARENT` | W3C traceparent (OTel) |
|
||||
|
||||
---
|
||||
|
||||
Powiązane: [[Control Plane]] | [[Orchestrator - PodBuilder i Spawner]] | [[Skill Sidecars i auto-RBAC]]
|
||||
59
02-Architektura/NATS JetStream - Event Bus.md
Normal file
59
02-Architektura/NATS JetStream - Event Bus.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# NATS JetStream - Event Bus
|
||||
|
||||
#sympozium #architektura #nats #messaging
|
||||
|
||||
## Rola w systemie
|
||||
|
||||
NATS JetStream pełni rolę **centralnego event bus** łączącego wszystkie komponenty Sympozium. Jest deployowany jako StatefulSet w namespace `sympozium-system`.
|
||||
|
||||
## Dlaczego NATS?
|
||||
|
||||
| Cecha | Wartość dla Sympozium |
|
||||
|-------|----------------------|
|
||||
| **Durable pub/sub** | Wiadomości nie są tracone przy restartach podów |
|
||||
| **Replay** | Kanały mogą odtworzyć niezrealizowane wiadomości |
|
||||
| **Lightweight** | Minimalne zasoby vs Kafka/RabbitMQ |
|
||||
| **Cloud-native** | Natywne wsparcie K8s |
|
||||
| **Decoupling** | Kanały i agenty nie muszą wiedzieć o sobie |
|
||||
|
||||
## Topologia
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ Channel Pods │ │ NATS │ │ Controller │
|
||||
│ (Telegram, │────►│ JetStream │◄────│ Manager │
|
||||
│ Slack, etc.)│◄────│ │────►│ │
|
||||
└──────────────┘ │ StatefulSet │ └──────────────┘
|
||||
│ sympozium- │
|
||||
┌──────────────┐ │ system │ ┌──────────────┐
|
||||
│ IPC Bridge │────►│ │ │ Schedule │
|
||||
│ (sidecars) │◄────│ │ │ Router │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Połączenie
|
||||
|
||||
Wszystkie komponenty łączą się pod adresem:
|
||||
```
|
||||
nats://nats.sympozium-system.svc:4222
|
||||
```
|
||||
|
||||
Zmienna środowiskowa: `EVENT_BUS_URL`
|
||||
|
||||
## Wzorzec komunikacji
|
||||
|
||||
1. **Request/Reply** - tool execution (request → sidecar → result)
|
||||
2. **Pub/Sub** - lifecycle events (run.started, run.completed)
|
||||
3. **Queue Groups** - channel messages (load-balanced between consumers)
|
||||
|
||||
## Dlaczego nie bezpośrednia komunikacja?
|
||||
|
||||
Agent pod nie ma dostępu sieciowego (NetworkPolicy deny-all). Jedyny komponent z dostępem do NATS to **IPC Bridge sidecar**. To zapewnia:
|
||||
|
||||
- Agent nie może bezpośrednio komunikować się z innymi podami
|
||||
- Całość komunikacji przechodzi przez kontrolowany kanał
|
||||
- Łatwe auditowanie (jeden punkt wejścia/wyjścia)
|
||||
|
||||
---
|
||||
|
||||
Powiązane: [[Przepływ danych i IPC]] | [[Control Plane]] | [[NetworkPolicy i izolacja sieciowa]]
|
||||
104
02-Architektura/Orchestrator - PodBuilder i Spawner.md
Normal file
104
02-Architektura/Orchestrator - PodBuilder i Spawner.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Orchestrator - PodBuilder i Spawner
|
||||
|
||||
#sympozium #architektura #orchestrator
|
||||
|
||||
## Lokalizacja
|
||||
|
||||
`internal/orchestrator/` - pakiet odpowiedzialny za budowanie specyfikacji podów i spawning Job'ów.
|
||||
|
||||
## PodBuilder
|
||||
|
||||
`PodBuilder` to struct odpowiedzialny za konstruowanie pod spec'ów. Konfigurowany jest tagiem obrazów:
|
||||
|
||||
```go
|
||||
type PodBuilder struct {
|
||||
DefaultAgentImage string // agent-runner
|
||||
DefaultIPCBridgeImage string // ipc-bridge
|
||||
DefaultSandboxImage string // sandbox
|
||||
DefaultMCPBridgeImage string // mcp-bridge
|
||||
EventBusURL string // nats://nats.sympozium-system.svc:4222
|
||||
ImageTag string // np. "v0.0.25"
|
||||
}
|
||||
```
|
||||
|
||||
Registry: `ghcr.io/sympozium-ai/sympozium`
|
||||
|
||||
## Budowanie kontenerów
|
||||
|
||||
### BuildAgentContainer
|
||||
Główny kontener agenta z:
|
||||
- Read-only root filesystem
|
||||
- Drop ALL capabilities
|
||||
- No privilege escalation
|
||||
- Woluminy: workspace, skills (ro), ipc, tmp
|
||||
- EnvFrom: secret z kluczem API
|
||||
|
||||
### BuildIPCBridgeContainer
|
||||
Sidecar IPC bridge z:
|
||||
- Wolumin ipc (shared z agentem)
|
||||
- Env: AGENT_RUN_ID, INSTANCE_NAME, EVENT_BUS_URL
|
||||
- Opcjonalnie: TRACEPARENT, OTEL_* (observability)
|
||||
|
||||
### BuildSandboxContainer
|
||||
Opcjonalny sidecar sandbox z:
|
||||
- Read-only root filesystem
|
||||
- Drop ALL capabilities
|
||||
- Command: `sleep infinity` (czeka na komendy z agenta)
|
||||
- Woluminy: workspace, tmp
|
||||
|
||||
### BuildVolumes
|
||||
4 woluminy:
|
||||
- `workspace` - emptyDir 1Gi
|
||||
- `ipc` - emptyDir (Memory medium) 64Mi - **RAM-backed** dla szybkości
|
||||
- `tmp` - emptyDir 256Mi
|
||||
- `skills` - Projected volume z ConfigMapów SkillPacks
|
||||
|
||||
## AgentPodConfig
|
||||
|
||||
Konfiguracja przekazywana do buildera:
|
||||
|
||||
```go
|
||||
type AgentPodConfig struct {
|
||||
RunID string
|
||||
InstanceName string
|
||||
AgentID string
|
||||
SessionKey string
|
||||
ModelProvider string
|
||||
ModelName string
|
||||
ThinkingMode string
|
||||
AuthSecretRef string
|
||||
SandboxEnabled bool
|
||||
SandboxImage string
|
||||
SpawnDepth int
|
||||
Skills []SkillMount
|
||||
Traceparent string // W3C traceparent
|
||||
OTelEndpoint string // OTLP endpoint
|
||||
}
|
||||
```
|
||||
|
||||
## Proces tworzenia poda (w AgentRunReconciler)
|
||||
|
||||
```
|
||||
1. reconcilePending()
|
||||
├── validatePolicy() - sprawdza SympoziumPolicy
|
||||
├── ensureAgentServiceAccount() - ServiceAccount w namespace
|
||||
├── createInputConfigMap() - task + system prompt
|
||||
├── resolveSkillSidecars() - SkillPack CRDs → sidecar specs
|
||||
├── ensureMCPConfigMap() - konfiguracja MCP serwerów
|
||||
├── buildContainers() - PodBuilder buduje spec
|
||||
├── createEphemeralRBAC() - Role + RoleBinding per sidecar
|
||||
└── createJob() / createSandboxCR() - finalne tworzenie zasobu K8s
|
||||
```
|
||||
|
||||
## Relacja z AgentRun Controller
|
||||
|
||||
`AgentRunReconciler` (`internal/controller/agentrun_controller.go`) jest "klientem" PodBuilder'a. Reconciler:
|
||||
1. Obserwuje AgentRun CRDs
|
||||
2. Używa PodBuilder do budowania spec'ów
|
||||
3. Tworzy Job/Sandbox CR w Kubernetes
|
||||
4. Monitoruje lifecycle poda
|
||||
5. Zbiera wyniki i czyści zasoby
|
||||
|
||||
---
|
||||
|
||||
Powiązane: [[Cykl życia Agent Pod]] | [[AgentRun]] | [[Cykl życia AgentRun]]
|
||||
126
02-Architektura/Przepływ danych i IPC.md
Normal file
126
02-Architektura/Przepływ danych i IPC.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Przepływ danych i IPC
|
||||
|
||||
#sympozium #architektura #ipc
|
||||
|
||||
## Mechanizm IPC
|
||||
|
||||
Sympozium używa **filesystem-based IPC** - agenty komunikują się z control plane przez pliki JSON w woluminie `/ipc/`:
|
||||
|
||||
```
|
||||
Agent tool pisze JSON → /ipc/<dir>/*.json → fsnotify watcher → NATS publish → Controller
|
||||
```
|
||||
|
||||
### Katalogi IPC
|
||||
|
||||
| Katalog | Cel | Przykład |
|
||||
|---------|-----|---------|
|
||||
| `/ipc/tools/` | Wykonanie komend w sidecarze | `execute_command` |
|
||||
| `/ipc/messages/` | Wysyłanie wiadomości na kanały | `send_channel_message` |
|
||||
| `/ipc/schedules/` | Zarządzanie schedulami | `schedule_task` |
|
||||
|
||||
## Dlaczego filesystem IPC?
|
||||
|
||||
### Zalety
|
||||
1. **Language-agnostic** - agent mógłby być w Pythonie, Rust, czymkolwiek
|
||||
2. **Zero zależności** - agent nie potrzebuje klienta NATS ani żadnego SDK
|
||||
3. **Inspekcja** - pliki JSON w woluminie można łatwo debugować
|
||||
4. **Prostota** - zapis pliku to najprostsza operacja I/O
|
||||
5. **Bezpieczeństwo** - agent nie ma dostępu sieciowego, tylko do woluminu
|
||||
|
||||
### Jak to działa
|
||||
|
||||
```
|
||||
1. Agent zapisuje /ipc/tools/cmd-12345.json:
|
||||
{
|
||||
"command": "kubectl get pods",
|
||||
"runId": "my-run-123"
|
||||
}
|
||||
|
||||
2. IPC Bridge (sidecar) wykrywa plik via fsnotify
|
||||
|
||||
3. Bridge publikuje na NATS:
|
||||
Topic: tool.exec.request
|
||||
Payload: {command, runId, instanceName}
|
||||
|
||||
4. Skill sidecar (lub controller) odbiera i wykonuje
|
||||
|
||||
5. Wynik wraca: NATS → IPC Bridge → /ipc/tools/result-12345.json
|
||||
|
||||
6. Agent czyta wynik z pliku
|
||||
```
|
||||
|
||||
## NATS Topics
|
||||
|
||||
Kluczowe tematy zdefiniowane w `internal/eventbus/types.go`:
|
||||
|
||||
### Lifecycle agenta
|
||||
- `agent.run.requested` - żądanie nowego runu
|
||||
- `agent.run.started` - run rozpoczęty
|
||||
- `agent.run.completed` - run zakończony sukcesem
|
||||
- `agent.run.failed` - run zakończony błędem
|
||||
|
||||
### Wiadomości kanałów
|
||||
- `channel.message.received` - wiadomość od użytkownika
|
||||
- `channel.message.send` - wiadomość do użytkownika
|
||||
|
||||
### Narzędzia
|
||||
- `tool.exec.request` - żądanie wykonania komendy w sidecarze
|
||||
- `tool.exec.result` - wynik wykonania
|
||||
|
||||
### Scheduling
|
||||
- `schedule.upsert` - agent sam tworzy/aktualizuje swój schedule
|
||||
|
||||
## Wbudowane narzędzia agenta
|
||||
|
||||
Agent-runner ma **7 wbudowanych narzędzi** (`cmd/agent-runner/tools.go`):
|
||||
|
||||
| Narzędzie | Kategoria | Opis |
|
||||
|-----------|-----------|------|
|
||||
| `execute_command` | IPC (sidecar) | Uruchamia komendy shell w skill sidecarze |
|
||||
| `read_file` | Native | Czyta zawartość pliku |
|
||||
| `write_file` | Native | Tworzy/zapisuje pliki |
|
||||
| `list_directory` | Native | Listuje zawartość katalogu |
|
||||
| `send_channel_message` | IPC (bridge) | Wysyła wiadomości na kanały |
|
||||
| `fetch_url` | Native | HTTP GET i zwraca body |
|
||||
| `schedule_task` | IPC (bridge) | CRUD na SympoziumSchedule CRDs |
|
||||
|
||||
### Natywne vs IPC
|
||||
|
||||
- **Native** - narzędzia wykonywane bezpośrednio w kontenerze agenta
|
||||
- **IPC (sidecar)** - narzędzia delegowane do skill sidecara przez IPC bridge
|
||||
- **IPC (bridge)** - narzędzia delegowane do controllera przez NATS
|
||||
|
||||
## Przepływ end-to-end
|
||||
|
||||
```
|
||||
Użytkownik → Telegram
|
||||
↓
|
||||
Channel Pod (Telegram) → NATS: channel.message.received
|
||||
↓
|
||||
Channel Router → Tworzy AgentRun CR
|
||||
↓
|
||||
AgentRun Reconciler → Tworzy Job z kontenerami
|
||||
↓
|
||||
Agent Container:
|
||||
1. Czyta task z /workspace/input/
|
||||
2. Czyta skills z /skills/
|
||||
3. Czyta memory z /memory/ lub memory API
|
||||
4. Wywołuje LLM (OpenAI/Anthropic/etc.)
|
||||
5. LLM decyduje o użyciu narzędzia
|
||||
6. Agent pisze do /ipc/tools/
|
||||
7. IPC Bridge → NATS → Skill Sidecar wykonuje
|
||||
8. Wynik wraca → Agent kontynuuje dialog z LLM
|
||||
9. Agent pisze wynik do stdout
|
||||
↓
|
||||
Controller zbiera logi poda
|
||||
↓
|
||||
Controller → NATS: agent.run.completed
|
||||
↓
|
||||
Channel Router → NATS: channel.message.send
|
||||
↓
|
||||
Channel Pod (Telegram) → Użytkownik
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Powiązane: [[NATS JetStream - Event Bus]] | [[Cykl życia Agent Pod]] | [[Skill Sidecars i auto-RBAC]]
|
||||
Reference in New Issue
Block a user