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'
|
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',
|
label: 'Tools',
|
||||||
name: 'agentTools',
|
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 && toolsInstance.length > 0) {
|
||||||
if (llmNodeInstance.bindTools === undefined) {
|
if (llmNodeInstance.bindTools === undefined) {
|
||||||
throw new Error(`Agent needs to have a function calling capable models.`)
|
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
|
// Track total tokens used throughout this process
|
||||||
let totalTokens = response.usage_metadata?.total_tokens || 0
|
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) {
|
if (!response.tool_calls || response.tool_calls.length === 0) {
|
||||||
return { response, usedTools: [], sourceDocuments: [], artifacts: [], totalTokens }
|
return { response, usedTools: [], sourceDocuments: [], artifacts: [], totalTokens }
|
||||||
|
|
@ -1669,6 +1739,23 @@ class Agent_Agentflow implements INode {
|
||||||
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
|
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
|
// Add LLM response with tool calls to messages
|
||||||
messages.push({
|
messages.push({
|
||||||
id: response.id,
|
id: response.id,
|
||||||
|
|
@ -1678,11 +1765,6 @@ class Agent_Agentflow implements INode {
|
||||||
usage_metadata: response.usage_metadata
|
usage_metadata: response.usage_metadata
|
||||||
})
|
})
|
||||||
|
|
||||||
const usedTools: IUsedTool[] = []
|
|
||||||
let sourceDocuments: Array<any> = []
|
|
||||||
let artifacts: any[] = []
|
|
||||||
let isWaitingForHumanInput: boolean | undefined
|
|
||||||
|
|
||||||
// Process each tool call
|
// Process each tool call
|
||||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||||
const toolCall = response.tool_calls[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
|
// Get LLM response after tool calls
|
||||||
let newResponse: AIMessageChunk
|
let newResponse: AIMessageChunk
|
||||||
|
|
||||||
|
|
@ -1925,6 +2018,10 @@ class Agent_Agentflow implements INode {
|
||||||
isWaitingForHumanInput?: boolean
|
isWaitingForHumanInput?: boolean
|
||||||
}> {
|
}> {
|
||||||
let llmNodeInstance = llmWithoutToolsBind
|
let llmNodeInstance = llmWithoutToolsBind
|
||||||
|
const usedTools: IUsedTool[] = []
|
||||||
|
let sourceDocuments: Array<any> = []
|
||||||
|
let artifacts: any[] = []
|
||||||
|
let isWaitingForHumanInput: boolean | undefined
|
||||||
|
|
||||||
const lastCheckpointMessages = humanInputAction?.data?.input?.messages ?? []
|
const lastCheckpointMessages = humanInputAction?.data?.input?.messages ?? []
|
||||||
if (!lastCheckpointMessages.length) {
|
if (!lastCheckpointMessages.length) {
|
||||||
|
|
@ -1950,6 +2047,23 @@ class Agent_Agentflow implements INode {
|
||||||
sseStreamer.streamCalledToolsEvent(chatId, JSON.stringify(response.tool_calls))
|
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
|
// Add LLM response with tool calls to messages
|
||||||
messages.push({
|
messages.push({
|
||||||
id: response.id,
|
id: response.id,
|
||||||
|
|
@ -1959,11 +2073,6 @@ class Agent_Agentflow implements INode {
|
||||||
usage_metadata: response.usage_metadata
|
usage_metadata: response.usage_metadata
|
||||||
})
|
})
|
||||||
|
|
||||||
const usedTools: IUsedTool[] = []
|
|
||||||
let sourceDocuments: Array<any> = []
|
|
||||||
let artifacts: any[] = []
|
|
||||||
let isWaitingForHumanInput: boolean | undefined
|
|
||||||
|
|
||||||
// Process each tool call
|
// Process each tool call
|
||||||
for (let i = 0; i < response.tool_calls.length; i++) {
|
for (let i = 0; i < response.tool_calls.length; i++) {
|
||||||
const toolCall = response.tool_calls[i]
|
const toolCall = response.tool_calls[i]
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ import {
|
||||||
IconCode,
|
IconCode,
|
||||||
IconWorldWww,
|
IconWorldWww,
|
||||||
IconPhoto,
|
IconPhoto,
|
||||||
IconBrandGoogle
|
IconBrandGoogle,
|
||||||
|
IconBrowserCheck
|
||||||
} from '@tabler/icons-react'
|
} from '@tabler/icons-react'
|
||||||
import StopCircleIcon from '@mui/icons-material/StopCircle'
|
import StopCircleIcon from '@mui/icons-material/StopCircle'
|
||||||
import CancelIcon from '@mui/icons-material/Cancel'
|
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(() => {
|
useEffect(() => {
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -455,6 +467,16 @@ const AgentFlowNode = ({ data }) => {
|
||||||
: [],
|
: [],
|
||||||
toolProperty: 'builtInTool',
|
toolProperty: 'builtInTool',
|
||||||
isBuiltInGemini: true
|
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 [
|
return [
|
||||||
<Box
|
<Box
|
||||||
key={`tool-${configIndex}-${toolIndex}`}
|
key={`tool-${configIndex}-${toolIndex}`}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue