Migrate existing callback handlers to the new Action system before adding orchestrator actions.
From handleCallbackQueryInner:
subagent_approve:<id> - approve pending subagent spawnsubagent_reject:<id> - reject pending subagent spawnmodule Omni.Agent.Telegram.Actions
( Action(..)
, ActionInput(..)
, ActionResult(..)
, ActionOutcome(..)
, executeAction
, actionRegistry
) where
-- Core types as designed in t-280.2.7
approveSubagentAction :: Action
approveSubagentAction = Action
{ actionId = "subagent_approve"
, actionExecute = \input -> do
let pendingId = aiPayload input
result <- Subagent.approveAndSpawnSubagentWithCallback pendingId Nothing
case result of
Left err -> pure ActionResult
{ arUserMessage = "[Approved subagent: " <> pendingId <> "]"
, arAssistantMessage = "Failed to spawn: " <> err
, arOutcome = ActionFailed err
}
Right subagentId -> pure ActionResult
{ arUserMessage = "[Approved subagent: " <> pendingId <> "]"
, arAssistantMessage = "Subagent " <> subagentId <> " queued! I'll notify you when it completes."
, arOutcome = ActionPending subagentId
}
}
rejectSubagentAction :: Action
-- similar
Replace the case statement with:
handleCallbackQueryInner tgConfig cq chatId userId callbackData = do
let (actionId, payload) = parseCallbackData callbackData
input = ActionInput userId chatId payload
result <- executeAction actionId input
case result of
Nothing -> do
answerCallbackQuery tgConfig (cqId cq) (Just "Unknown action")
putText <| "Unknown callback: " <> callbackData
Just ar -> do
-- Log to conversation (type system guarantees these fields exist)
Memory.appendMessage chatId User (arUserMessage ar)
Memory.appendMessage chatId Assistant (arAssistantMessage ar)
-- Send response
sendMessage tgConfig chatId (arAssistantMessage ar)
answerCallbackQuery tgConfig (cqId cq) (Just "Done")
Ensure buttons use actionId format: actionId:payload
t-280.2.7 (design task - but can do both together)