Skip to content

Commit aabd021

Browse files
Ambient Code Botclaude
authored andcommitted
fix: route scheduled follow-up prompts through backend AG-UI proxy
The trigger was posting directly to the runner, bypassing the backend's AG-UI proxy. Events from these runs weren't persisted or broadcast to the UI, so the user couldn't see the response. Now the trigger posts to the backend's /agui/run endpoint using its service account token. The backend proxy handles event persistence and broadcasting to UI subscribers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 473dfda commit aabd021

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

components/manifests/deploy.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,12 @@ fi
356356
echo -e "${BLUE}Updating operator with custom runner image...${NC}"
357357
oc patch deployment agentic-operator -n ${NAMESPACE} -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"agentic-operator\",\"env\":[{\"name\":\"AMBIENT_CODE_RUNNER_IMAGE\",\"value\":\"${DEFAULT_RUNNER_IMAGE}\"}]}]}}}}" --type=strategic
358358

359+
# Pin OPERATOR_IMAGE in operator-config so scheduled session triggers use the correct image
360+
echo -e "${BLUE}Pinning OPERATOR_IMAGE in operator-config configmap...${NC}"
361+
oc patch configmap operator-config -n ${NAMESPACE} \
362+
--type=merge -p "{\"data\":{\"OPERATOR_IMAGE\":\"${DEFAULT_OPERATOR_IMAGE}\"}}" 2>/dev/null || \
363+
oc create configmap operator-config -n ${NAMESPACE} --from-literal=OPERATOR_IMAGE="${DEFAULT_OPERATOR_IMAGE}" 2>/dev/null || true
364+
359365
# Update agent-registry configmap with custom runner and state-sync images
360366
echo -e "${BLUE}Updating agent-registry configmap with custom images...${NC}"
361367
REGISTRY_JSON=$(oc get configmap ambient-agent-registry -n ${NAMESPACE} -o jsonpath='{.data.agent-registry\.json}')

components/operator/internal/trigger/trigger.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"k8s.io/client-go/rest"
2020
"k8s.io/client-go/util/retry"
2121

22-
"ambient-code-operator/internal/handlers"
2322
"ambient-code-operator/internal/types"
2423
)
2524

@@ -143,9 +142,17 @@ func tryReuseLastSession(dynamicClient dynamic.Interface, namespace, scheduledSe
143142
}
144143
}
145144

146-
// sendFollowUpPrompt sends a prompt to a running session via the runner's AG-UI endpoint.
145+
// sendFollowUpPrompt sends a prompt to a running session via the backend's AG-UI proxy.
146+
// This ensures events are persisted and broadcast to the UI.
147147
func sendFollowUpPrompt(namespace, sessionName, prompt string) error {
148-
runnerURL := fmt.Sprintf("http://session-%s.%s.svc.cluster.local:%d/", sessionName, namespace, handlers.DefaultRunnerPort)
148+
backendNS := os.Getenv("BACKEND_NAMESPACE")
149+
if backendNS == "" {
150+
backendNS = "ambient-code"
151+
}
152+
backendURL := fmt.Sprintf(
153+
"http://backend-service.%s.svc.cluster.local:8080/api/projects/%s/agentic-sessions/%s/agui/run",
154+
backendNS, namespace, sessionName,
155+
)
149156

150157
input := map[string]interface{}{
151158
"threadId": sessionName,
@@ -164,24 +171,31 @@ func sendFollowUpPrompt(namespace, sessionName, prompt string) error {
164171
return fmt.Errorf("failed to marshal run input: %v", err)
165172
}
166173

167-
req, err := http.NewRequest("POST", runnerURL, bytes.NewReader(body))
174+
// Read the service account token for backend auth
175+
token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
176+
if err != nil {
177+
return fmt.Errorf("failed to read service account token: %v", err)
178+
}
179+
180+
req, err := http.NewRequest("POST", backendURL, bytes.NewReader(body))
168181
if err != nil {
169182
return fmt.Errorf("failed to create request: %v", err)
170183
}
171184
req.Header.Set("Content-Type", "application/json")
185+
req.Header.Set("Authorization", "Bearer "+string(token))
172186

173187
client := &http.Client{Timeout: 30 * time.Second}
174188
resp, err := client.Do(req)
175189
if err != nil {
176-
return fmt.Errorf("failed to send request to runner: %v", err)
190+
return fmt.Errorf("failed to send request to backend: %v", err)
177191
}
178192
defer resp.Body.Close()
179193

180194
if resp.StatusCode >= 400 {
181-
return fmt.Errorf("runner returned status %d", resp.StatusCode)
195+
return fmt.Errorf("backend returned status %d", resp.StatusCode)
182196
}
183197

184-
log.Printf("Successfully sent follow-up prompt to session %s (status %d)", sessionName, resp.StatusCode)
198+
log.Printf("Successfully sent follow-up prompt to session %s via backend (status %d)", sessionName, resp.StatusCode)
185199
return nil
186200
}
187201

0 commit comments

Comments
 (0)