summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Omni/Agent/Prompts.hs2
-rw-r--r--Omni/Agent/Subagent.hs36
-rw-r--r--Omni/Agent/Subagent/Coder.hs22
-rw-r--r--Omni/Agent/Telegram.hs24
-rw-r--r--Omni/Dev/Beryllium/Ava.nix8
5 files changed, 77 insertions, 15 deletions
diff --git a/Omni/Agent/Prompts.hs b/Omni/Agent/Prompts.hs
index 231df3c..70414ca 100644
--- a/Omni/Agent/Prompts.hs
+++ b/Omni/Agent/Prompts.hs
@@ -80,7 +80,7 @@ test =
"Omni.Agent.Prompts"
[ Test.unit "promptPath constructs correct path" <| do
let path = promptPath "agents/telegram/system"
- ("agents/telegram/system.md" `List.isSuffixOf` path) Test.@=? True,
+ ("agents/telegram/system.mustache" `List.isSuffixOf` path) Test.@=? True,
Test.unit "parsePromptMetadata parses frontmatter" <| do
let content =
"---\n\
diff --git a/Omni/Agent/Subagent.hs b/Omni/Agent/Subagent.hs
index f5e04b0..9f3052d 100644
--- a/Omni/Agent/Subagent.hs
+++ b/Omni/Agent/Subagent.hs
@@ -18,6 +18,8 @@
-- : out omni-agent-subagent
-- : dep aeson
-- : dep async
+-- : dep directory
+-- : dep mustache
-- : dep stm
-- : dep uuid
module Omni.Agent.Subagent
@@ -92,6 +94,7 @@ import qualified Data.UUID
import qualified Data.UUID.V4
import qualified Omni.Agent.AuditLog as AuditLog
import qualified Omni.Agent.Engine as Engine
+import qualified Omni.Agent.Prompts as Prompts
import qualified Omni.Agent.Provider as Provider
import qualified Omni.Agent.Subagent.Coder as Coder
import qualified Omni.Agent.Tools as Tools
@@ -611,6 +614,21 @@ toolsForRole Researcher keys =
toolsForRole Coder _keys = Coder.coderTools
toolsForRole (CustomRole _) keys = toolsForRole Researcher keys
+-- | Load system prompt from template, falling back to hardcoded if unavailable
+loadSystemPromptForRole :: SubagentRole -> Text -> Maybe Text -> IO Text
+loadSystemPromptForRole role task maybeContext = do
+ let ctx =
+ Aeson.object
+ [ "role_description" .= roleDescription role,
+ "task" .= task,
+ "context" .= maybeContext
+ ]
+ result <- Prompts.renderPrompt "subagents/generic/system" ctx
+ case result of
+ Right prompt -> pure prompt
+ Left _err -> pure (systemPromptForRole role task maybeContext)
+
+-- | Hardcoded fallback prompt for subagents
systemPromptForRole :: SubagentRole -> Text -> Maybe Text -> Text
systemPromptForRole role task maybeContext =
Text.unlines
@@ -647,14 +665,14 @@ systemPromptForRole role task maybeContext =
"}",
"```"
]
- where
- roleDescription :: SubagentRole -> Text
- roleDescription WebCrawler = "web research"
- roleDescription CodeReviewer = "code review"
- roleDescription DataExtractor = "data extraction"
- roleDescription Researcher = "research"
- roleDescription Coder = "coding"
- roleDescription (CustomRole name) = name
+
+roleDescription :: SubagentRole -> Text
+roleDescription WebCrawler = "web research"
+roleDescription CodeReviewer = "code review"
+roleDescription DataExtractor = "data extraction"
+roleDescription Researcher = "research"
+roleDescription Coder = "coding"
+roleDescription (CustomRole name) = name
runSubagent :: SubagentApiKeys -> SubagentConfig -> IO SubagentResult
runSubagent keys config = runSubagentWithCallbacks keys config defaultCallbacks
@@ -778,7 +796,7 @@ runGenericSubagent keys config callbacks = do
let role = subagentRole config
let model = fromMaybe (modelForRole role) (subagentModel config)
let tools = toolsForRole role keys
- let systemPrompt = systemPromptForRole role (subagentTask config) (subagentContext config)
+ systemPrompt <- loadSystemPromptForRole role (subagentTask config) (subagentContext config)
onSubagentStart callbacks ("Starting " <> tshow role <> " subagent...")
diff --git a/Omni/Agent/Subagent/Coder.hs b/Omni/Agent/Subagent/Coder.hs
index 523b035..865a97e 100644
--- a/Omni/Agent/Subagent/Coder.hs
+++ b/Omni/Agent/Subagent/Coder.hs
@@ -17,6 +17,8 @@
-- : out omni-agent-subagent-coder
-- : dep aeson
-- : dep async
+-- : dep directory
+-- : dep mustache
-- : dep stm
-- : dep time
module Omni.Agent.Subagent.Coder
@@ -52,6 +54,7 @@ import qualified Data.Aeson as Aeson
import qualified Data.Text as Text
import qualified Data.Time.Clock as Clock
import qualified Omni.Agent.Engine as Engine
+import qualified Omni.Agent.Prompts as Prompts
import qualified Omni.Agent.Provider as Provider
import qualified Omni.Agent.Tools as Tools
import qualified Omni.Test as Test
@@ -242,7 +245,22 @@ coderTools =
Tools.searchAndReadTool
]
--- | System prompt for the Coder subagent
+-- | Load system prompt from template, falling back to hardcoded if unavailable
+loadCoderSystemPrompt :: CoderConfig -> Maybe Text -> IO Text
+loadCoderSystemPrompt cfg maybeInitState = do
+ let ctx =
+ Aeson.object
+ [ "namespace" .= coderNamespace cfg,
+ "task" .= coderTask cfg,
+ "context" .= coderContext cfg,
+ "init_state" .= maybeInitState
+ ]
+ result <- Prompts.renderPrompt "subagents/coder/system" ctx
+ case result of
+ Right prompt -> pure prompt
+ Left _err -> pure (coderSystemPrompt cfg maybeInitState)
+
+-- | Hardcoded fallback system prompt for the Coder subagent
coderSystemPrompt :: CoderConfig -> Maybe Text -> Text
coderSystemPrompt cfg maybeInitState =
Text.unlines
@@ -364,7 +382,7 @@ runWorkVerifyLoop openRouterKey cfg initState verifyAttempt accTokens accCost =
-- Phase 2: Work (run the agent)
let provider = Provider.defaultOpenRouter openRouterKey (coderModel cfg)
- let systemPrompt = coderSystemPrompt cfg initState
+ systemPrompt <- loadCoderSystemPrompt cfg initState
let guardrails =
Engine.Guardrails
{ Engine.guardrailMaxCostCents = coderMaxCost cfg - accCost,
diff --git a/Omni/Agent/Telegram.hs b/Omni/Agent/Telegram.hs
index 0ebf4ca..7b2beaa 100644
--- a/Omni/Agent/Telegram.hs
+++ b/Omni/Agent/Telegram.hs
@@ -13,7 +13,9 @@
--
-- : out omni-agent-telegram
-- : dep aeson
+-- : dep directory
-- : dep http-conduit
+-- : dep mustache
-- : dep stm
-- : dep HaskellNet
-- : dep HaskellNet-SSL
@@ -85,6 +87,7 @@ import qualified Omni.Agent.AuditLog as AuditLog
import qualified Omni.Agent.Engine as Engine
import qualified Omni.Agent.Memory as Memory
import qualified Omni.Agent.Paths as Paths
+import qualified Omni.Agent.Prompts as Prompts
import qualified Omni.Agent.Provider as Provider
import qualified Omni.Agent.Skills as Skills
import qualified Omni.Agent.Subagent as Subagent
@@ -154,8 +157,20 @@ test =
benChatId :: Int
benChatId = 33193730
+-- | Load system prompt from template, falling back to hardcoded if unavailable
+loadTelegramSystemPrompt :: IO Text
+loadTelegramSystemPrompt = do
+ result <- Prompts.renderPrompt "agents/telegram/system" (Aeson.object [])
+ case result of
+ Right prompt -> pure prompt
+ Left _err -> pure telegramSystemPromptFallback
+
+-- | Hardcoded fallback prompt (used if template not found)
telegramSystemPrompt :: Text
-telegramSystemPrompt =
+telegramSystemPrompt = telegramSystemPromptFallback
+
+telegramSystemPromptFallback :: Text
+telegramSystemPromptFallback =
Text.unlines
[ "don't worry about formalities. respond conversationally, in short messages, not long essays. ask follow up questions before answering if you need to.",
"",
@@ -1100,8 +1115,11 @@ processEngagedMessage tgConfig provider engineCfg msg uid userName chatId userMe
"prioritize: urgent items first, then emails needing response, then suggest unsubscribing from marketing."
]
else ""
- systemPrompt =
- telegramSystemPrompt
+
+ basePrompt <- loadTelegramSystemPrompt
+
+ let systemPrompt =
+ basePrompt
<> "\n\n## Current Date and Time\n"
<> timeStr
<> chatContext
diff --git a/Omni/Dev/Beryllium/Ava.nix b/Omni/Dev/Beryllium/Ava.nix
index d732249..becbf9e 100644
--- a/Omni/Dev/Beryllium/Ava.nix
+++ b/Omni/Dev/Beryllium/Ava.nix
@@ -83,6 +83,14 @@ in {
"d /home/ava 0755 ava users -"
"d /home/ava/omni 0755 ava users -"
"d /home/ava/skills 0755 ava users -"
+ "d /home/ava/prompts 0755 ava users -"
+ "d /home/ava/prompts/agents 0755 ava users -"
+ "d /home/ava/prompts/agents/telegram 0755 ava users -"
+ "d /home/ava/prompts/shared 0755 ava users -"
+ "d /home/ava/prompts/shared/formatting 0755 ava users -"
+ "d /home/ava/prompts/subagents 0755 ava users -"
+ "d /home/ava/prompts/subagents/generic 0755 ava users -"
+ "d /home/ava/prompts/subagents/coder 0755 ava users -"
"d /home/ava/outreach 0755 ava users -"
"d /home/ava/outreach/pending 0755 ava users -"
"d /home/ava/outreach/approved 0755 ava users -"