-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAgentChatSample.fs
More file actions
104 lines (92 loc) · 4.14 KB
/
AgentChatSample.fs
File metadata and controls
104 lines (92 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
module StockAdvisorFS.AgentChatSample
open System
open System.Threading.Tasks
open AgentNet
open Anthropic
open Microsoft.Extensions.AI
// ============================================================================
// AGENT CHAT SAMPLE
// Demonstrates creating an AI agent with tools and interactive chat.
// Uses Claude via the Anthropic API.
// ============================================================================
let private failIfNone msg opt = opt |> Option.defaultWith (fun () -> failwith msg)
let private tryGetEnv = Environment.GetEnvironmentVariable >> Option.ofObj
let private createChatClient () =
let apiKey = tryGetEnv "ANTHROPIC_API_KEY" |> failIfNone "ANTHROPIC_API_KEY environment variable is not set."
let model = tryGetEnv "ANTHROPIC_MODEL" |> Option.defaultValue "claude-sonnet-4-20250514"
let client = new AnthropicClient(ApiKey = apiKey)
client.AsIChatClient(model)
let private createStockAdvisor (chatClient: IChatClient) =
// Create tools using XML doc comments for descriptions
let stockInfoTool = Tool.createWithDocs <@ StockTools.getStockInfo @>
let historicalTool = Tool.createWithDocs <@ StockTools.getHistoricalPrices @>
let volatilityTool = Tool.createWithDocs <@ StockTools.calculateVolatility @>
let compareTool = Tool.createWithDocs <@ StockTools.compareStocks @>
ChatAgent.create """
You are a helpful stock analysis assistant. You help users analyze stocks,
compare investments, and understand market metrics.
When a user asks about stocks:
1. Use the available tools to gather relevant data
2. Analyze the information
3. Provide clear, actionable insights
After providing your analysis, also consider broader market context:
- Market sector trends
- Economic factors that might affect the stock
- Risk considerations based on current market conditions
- A final investment recommendation summary
Be concise but thorough in your analysis."""
|> ChatAgent.withName "StockAdvisor"
|> ChatAgent.withTools [stockInfoTool; historicalTool; volatilityTool; compareTool]
|> ChatAgent.build chatClient
let private chatLoop (agent: ChatAgent) = task {
printfn "\nAgent Chat Mode - Type 'back' to return to menu\n"
let rec loop () = task {
printf "You: "
let input = Console.ReadLine()
if String.IsNullOrWhiteSpace(input) then
return! loop ()
elif input.Equals("back", StringComparison.OrdinalIgnoreCase) then
return ()
else
printf "\nStockAdvisor: "
let stream = agent.ChatStream(input)
let enumerator = stream.GetAsyncEnumerator()
try
let mutable hasMore = true
while hasMore do
let! next = enumerator.MoveNextAsync()
if next then
match enumerator.Current with
| TextDelta t -> printf "%s" t
| ReasoningDelta _ -> ()
| ToolCallDelta u ->
if u.IsStart then
let name = u.Name |> Option.defaultValue "tool"
printfn $"\n[calling {name}...]"
| Completed _ -> printfn "\n"
else
hasMore <- false
finally
enumerator.DisposeAsync().AsTask().Wait()
return! loop ()
}
do! loop ()
}
/// Runs the agent chat sample. Returns the agent for reuse.
let run (existingAgent: ChatAgent option) : Task<ChatAgent option> = task {
match existingAgent with
| Some agent ->
do! chatLoop agent
return Some agent
| None ->
printfn "\nInitializing agent (requires Anthropic API key)..."
try
let chatClient = createChatClient ()
let agent = createStockAdvisor chatClient
do! chatLoop agent
return Some agent
with ex ->
printfn $"\nError: {ex.Message}"
printfn "Agent chat requires ANTHROPIC_API_KEY environment variable."
return None
}