add anthropic built in tools
This commit is contained in:
parent
e7ed4311ee
commit
b28e18e9a2
|
|
@ -182,6 +182,35 @@ class Agent_Agentflow implements INode {
|
|||
agentModel: 'chatGoogleGenerativeAI'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Anthropic Built-in Tools',
|
||||
name: 'agentToolsBuiltInAnthropic',
|
||||
type: 'multiOptions',
|
||||
optional: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Web Search',
|
||||
name: 'web_search_20250305',
|
||||
description: 'Search the web for the latest information'
|
||||
},
|
||||
{
|
||||
label: 'Web Fetch',
|
||||
name: 'web_fetch_20250910',
|
||||
description: 'Retrieve full content from specified web pages'
|
||||
}
|
||||
/*
|
||||
* Not supported yet as we need to get bash_code_execution_tool_result from content:
|
||||
https://docs.claude.com/en/docs/agents-and-tools/tool-use/code-execution-tool#retrieve-generated-files
|
||||
{
|
||||
label: 'Code Interpreter',
|
||||
name: 'code_execution_20250825',
|
||||
description: 'Write and run Python code in a sandboxed environment'
|
||||
}*/
|
||||
],
|
||||
show: {
|
||||
agentModel: 'chatAnthropic'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Tools',
|
||||
name: 'agentTools',
|
||||
|
|
@ -803,6 +832,43 @@ class Agent_Agentflow implements INode {
|
|||
}
|
||||
}
|
||||
|
||||
const agentToolsBuiltInAnthropic = convertMultiOptionsToStringArray(nodeData.inputs?.agentToolsBuiltInAnthropic)
|
||||
if (agentToolsBuiltInAnthropic && agentToolsBuiltInAnthropic.length > 0) {
|
||||
for (const tool of agentToolsBuiltInAnthropic) {
|
||||
// split _ to get the tool name by removing the last part (date)
|
||||
const toolName = tool.split('_').slice(0, -1).join('_')
|
||||
|
||||
if (tool === 'code_execution_20250825') {
|
||||
;(llmNodeInstance as any).clientOptions = {
|
||||
defaultHeaders: {
|
||||
'anthropic-beta': ['code-execution-2025-08-25', 'files-api-2025-04-14']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tool === 'web_fetch_20250910') {
|
||||
;(llmNodeInstance as any).clientOptions = {
|
||||
defaultHeaders: {
|
||||
'anthropic-beta': ['web-fetch-2025-09-10']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const builtInTool: ICommonObject = {
|
||||
type: tool,
|
||||
name: toolName
|
||||
}
|
||||
;(toolsInstance as any).push(builtInTool)
|
||||
;(availableTools as any).push({
|
||||
name: tool,
|
||||
toolNode: {
|
||||
label: tool,
|
||||
name: tool
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (llmNodeInstance && toolsInstance.length > 0) {
|
||||
if (llmNodeInstance.bindTools === undefined) {
|
||||
throw new Error(`Agent needs to have a function calling capable models.`)
|
||||
|
|
@ -1659,6 +1725,10 @@ class Agent_Agentflow implements INode {
|
|||
}> {
|
||||
// Track total tokens used throughout this process
|
||||
let totalTokens = response.usage_metadata?.total_tokens || 0
|
||||
const usedTools: IUsedTool[] = []
|
||||
let sourceDocuments: Array<any> = []
|
||||
let artifacts: any[] = []
|
||||
let isWaitingForHumanInput: boolean | undefined
|
||||
|
||||
if (!response.tool_calls || response.tool_calls.length === 0) {
|
||||
return { response, usedTools: [], sourceDocuments: [], artifacts: [], totalTokens }
|
||||
|
|
@ -1669,6 +1739,23 @@ class Agent_Agentflow implements INode {
|
|||
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
|
||||
}
|
||||
|
||||
const toBeRemovedToolCalls = []
|
||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||
const toolCall = response.tool_calls[i]
|
||||
if (!toolCall.id) {
|
||||
toBeRemovedToolCalls.push(toolCall)
|
||||
usedTools.push({
|
||||
tool: toolCall.name || 'tool',
|
||||
toolInput: toolCall.args,
|
||||
toolOutput: response.content
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const toolCall of toBeRemovedToolCalls) {
|
||||
response.tool_calls.splice(response.tool_calls.indexOf(toolCall), 1)
|
||||
}
|
||||
|
||||
// Add LLM response with tool calls to messages
|
||||
messages.push({
|
||||
id: response.id,
|
||||
|
|
@ -1678,11 +1765,6 @@ class Agent_Agentflow implements INode {
|
|||
usage_metadata: response.usage_metadata
|
||||
})
|
||||
|
||||
const usedTools: IUsedTool[] = []
|
||||
let sourceDocuments: Array<any> = []
|
||||
let artifacts: any[] = []
|
||||
let isWaitingForHumanInput: boolean | undefined
|
||||
|
||||
// Process each tool call
|
||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||
const toolCall = response.tool_calls[i]
|
||||
|
|
@ -1826,6 +1908,17 @@ class Agent_Agentflow implements INode {
|
|||
}
|
||||
}
|
||||
|
||||
if (response.tool_calls.length === 0) {
|
||||
const responseContent = typeof response.content === 'string' ? response.content : JSON.stringify(response.content, null, 2)
|
||||
return {
|
||||
response: new AIMessageChunk(responseContent),
|
||||
usedTools,
|
||||
sourceDocuments,
|
||||
artifacts,
|
||||
totalTokens
|
||||
}
|
||||
}
|
||||
|
||||
// Get LLM response after tool calls
|
||||
let newResponse: AIMessageChunk
|
||||
|
||||
|
|
@ -1925,6 +2018,10 @@ class Agent_Agentflow implements INode {
|
|||
isWaitingForHumanInput?: boolean
|
||||
}> {
|
||||
let llmNodeInstance = llmWithoutToolsBind
|
||||
const usedTools: IUsedTool[] = []
|
||||
let sourceDocuments: Array<any> = []
|
||||
let artifacts: any[] = []
|
||||
let isWaitingForHumanInput: boolean | undefined
|
||||
|
||||
const lastCheckpointMessages = humanInputAction?.data?.input?.messages ?? []
|
||||
if (!lastCheckpointMessages.length) {
|
||||
|
|
@ -1950,6 +2047,23 @@ class Agent_Agentflow implements INode {
|
|||
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
|
||||
}
|
||||
|
||||
const toBeRemovedToolCalls = []
|
||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||
const toolCall = response.tool_calls[i]
|
||||
if (!toolCall.id) {
|
||||
toBeRemovedToolCalls.push(toolCall)
|
||||
usedTools.push({
|
||||
tool: toolCall.name || 'tool',
|
||||
toolInput: toolCall.args,
|
||||
toolOutput: response.content
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const toolCall of toBeRemovedToolCalls) {
|
||||
response.tool_calls.splice(response.tool_calls.indexOf(toolCall), 1)
|
||||
}
|
||||
|
||||
// Add LLM response with tool calls to messages
|
||||
messages.push({
|
||||
id: response.id,
|
||||
|
|
@ -1959,11 +2073,6 @@ class Agent_Agentflow implements INode {
|
|||
usage_metadata: response.usage_metadata
|
||||
})
|
||||
|
||||
const usedTools: IUsedTool[] = []
|
||||
let sourceDocuments: Array<any> = []
|
||||
let artifacts: any[] = []
|
||||
let isWaitingForHumanInput: boolean | undefined
|
||||
|
||||
// Process each tool call
|
||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||
const toolCall = response.tool_calls[i]
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ import {
|
|||
IconCode,
|
||||
IconWorldWww,
|
||||
IconPhoto,
|
||||
IconBrandGoogle
|
||||
IconBrandGoogle,
|
||||
IconBrowserCheck
|
||||
} from '@tabler/icons-react'
|
||||
import StopCircleIcon from '@mui/icons-material/StopCircle'
|
||||
import CancelIcon from '@mui/icons-material/Cancel'
|
||||
|
|
@ -154,6 +155,17 @@ const AgentFlowNode = ({ data }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const getBuiltInAnthropicToolIcon = (toolName) => {
|
||||
switch (toolName) {
|
||||
case 'web_search_20250305':
|
||||
return <IconWorldWww size={14} color={'white'} />
|
||||
case 'web_fetch_20250910':
|
||||
return <IconBrowserCheck size={14} color={'white'} />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
setTimeout(() => {
|
||||
|
|
@ -455,6 +467,16 @@ const AgentFlowNode = ({ data }) => {
|
|||
: [],
|
||||
toolProperty: 'builtInTool',
|
||||
isBuiltInGemini: true
|
||||
},
|
||||
{
|
||||
tools: data.inputs?.agentToolsBuiltInAnthropic
|
||||
? (typeof data.inputs.agentToolsBuiltInAnthropic === 'string'
|
||||
? JSON.parse(data.inputs.agentToolsBuiltInAnthropic)
|
||||
: data.inputs.agentToolsBuiltInAnthropic
|
||||
).map((tool) => ({ builtInTool: tool }))
|
||||
: [],
|
||||
toolProperty: 'builtInTool',
|
||||
isBuiltInAnthropic: true
|
||||
}
|
||||
]
|
||||
|
||||
|
|
@ -541,6 +563,32 @@ const AgentFlowNode = ({ data }) => {
|
|||
]
|
||||
}
|
||||
|
||||
// Handle built-in Anthropic tools with icons
|
||||
if (config.isBuiltInAnthropic) {
|
||||
const icon = getBuiltInAnthropicToolIcon(toolName)
|
||||
if (!icon) return []
|
||||
|
||||
return [
|
||||
<Box
|
||||
key={`tool-${configIndex}-${toolIndex}`}
|
||||
sx={{
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: customization.isDarkMode
|
||||
? darken(data.color, 0.5)
|
||||
: darken(data.color, 0.2),
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 0.2
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</Box>
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
<Box
|
||||
key={`tool-${configIndex}-${toolIndex}`}
|
||||
|
|
|
|||
Loading…
Reference in New Issue