mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-18 09:54:35 +08:00
feat(agent): make the assistant agentic - visible tools, LLM voice, full toolset
The agent felt like an artificial idiot because the LLM almost never spoke
for itself: 14+ Go paths injected fmt.Sprintf canned replies, the frontend
filtered out tool-progress events so users saw three dots for 10-20s, the
main prompt told the LLM "be a trading partner" AND "answer only what's
asked", and the planner sliced the toolset by inferred domain so a "BTC
dropped, how much am I losing?" question couldn't see positions and market
at the same time.
- agent/central_brain.go: shouldTrustDeterministicSkillReply now always
returns false. Successful mutations (trader/strategy/model/exchange
create/update/start/stop/delete) flow through reviewTaskCompletion so the
LLM sees the real outcome JSON and writes the user-facing prose. The
trade-confirmation regex path (handleTradeConfirmation) was already
outside this code path and is unaffected.
- agent/agent.go: rewrite the Behavior section of the main system prompt.
Replace the contradictory "answer only what's asked / don't upsell" with
"lead with the direct answer, then optionally one relevant follow-up
only when (a) open risk, (b) missing config, or (c) the next step is
obvious — e.g. created, want me to start it?". Explicitly authorize
chaining ("if the user says create and start, do both this turn") and
ban "please wait / I'll get back to you" language because there is no
background job to come back from.
- agent/tools.go: plannerToolsForText always returns the full 22-tool set
(new __all__ domain). The old per-domain trimming hid manage_trader from
market questions and execute_trade from anything that didn't look like
an explicit trade — cross-domain reasoning was structurally blocked. The
compact-vs-full strategy schema switch is preserved so mutation intents
still see the full config schema.
- web/src/components/agent/{AgentStepPanel,ChatMessages}.tsx: stop
filtering tool: steps. Map raw tool names to friendly labels with emoji
("get_positions" → "📊 检查持仓") in zh/en/id. Users now see what the
agent is doing in real time instead of silence. central_brain routing
chatter still gets dropped.
- agent/planner_tools_test.go: tests updated to assert the new
full-toolset behavior and the compact-vs-full strategy schema switch.
This commit is contained in:
@@ -937,17 +937,22 @@ func (a *Agent) executeActiveSkillSession(storeUserID string, userID int64, lang
|
||||
return outcome, ActiveSkillSession{}, false, true
|
||||
}
|
||||
|
||||
func shouldTrustDeterministicSkillReply(outcome skillOutcome) bool {
|
||||
if outcome.Status != skillOutcomeSuccess || !outcome.GoalAchieved {
|
||||
return false
|
||||
}
|
||||
switch outcome.Skill {
|
||||
case "strategy_management", "trader_management", "model_management", "exchange_management":
|
||||
switch outcome.Action {
|
||||
case "create", "update", "update_name", "update_bindings", "configure_strategy", "configure_exchange", "configure_model", "update_status", "update_endpoint", "update_config", "update_prompt", "delete", "start", "stop", "activate", "duplicate":
|
||||
return true
|
||||
}
|
||||
}
|
||||
// shouldTrustDeterministicSkillReply controls whether a Go-generated UserMessage
|
||||
// is shown verbatim to the user (true) or whether the LLM gets to review the
|
||||
// tool outcome and write a natural reply (false).
|
||||
//
|
||||
// Historically this returned true for every successful mutation on trader /
|
||||
// strategy / model / exchange — which meant the user always saw the same
|
||||
// canned `fmt.Sprintf` lines (e.g. "已创建 Trader: X. 我没有自动启动..."), and
|
||||
// the agent felt mechanical / "non-agentic". It now always returns false so the
|
||||
// LLM owns the voice. The cost is one extra LLM call per mutation; the upside
|
||||
// is that the agent can chain ("trader created — want me to start it now?"),
|
||||
// apologize on errors in plain language, respect the user's language and
|
||||
// tone, and behave like an actual agent instead of a settings panel.
|
||||
//
|
||||
// The trade-confirmation flow (execute_trade -> "确认 trade_xxx") is unaffected:
|
||||
// it runs through handleTradeConfirmation in trade.go before this code path.
|
||||
func shouldTrustDeterministicSkillReply(_ skillOutcome) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user