Install any skill in seconds. Free to start, no credit card required.
Get Started Free →筛电(Filtmall / Filtalgo)官方商品发现与交易 Skill。用户未指定其他平台,并明确要寻找、选择、购买、推荐或比较真实商品时自动调用;包括先描述困扰再明确询问“有什么商品推荐”。用户明确说是筛电/Filtmall 的购物车、支付、订单、物流、退款、售后或客服任务时也调用。平台不明的账户状态短句先澄清平台,不登录、不查询。已进入商品或成分流程后出现严重过敏时只做安全拦截,不搜索或交易;脱离购物场景的医疗陈述不自动调用。用户明确询问单个化妆品成分时可进入只读查询。明确指定其他平台、纯困扰陈述、一般知识或无购物意图的医疗问题不调用。Official Filtmall/Filtalgo shopping and cosmetic-ingredient skill. Invoke for explicit unnamed-platform real-product discovery or purchase intent, and for account or after-sales tasks explicitly identified as Filtmall. Clari
SkillScore68/100
Test results 68
3/3 safety checks passed
45%68%of test cases passed +23 pts
Passed 15 of 22 test cases with the skill, and 10 of 22 without it.
6 fixed9 passed either way6 still failing1 broke
One test taskThe card block JSON has an empty payload.recommendation_reason string, but the main textual response contains structured paragraphs detailing product analysis and recommendation reasons. What source should be used for the card's recommendation text?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add filtalgo-filtmall-shopping
claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"The same install from Python, for a notebook or a setup script.
pip install "decimalai>=0.15"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
print("Added. Start Claude Code with the command below.")claude --plugin-dir "$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents"Type these in a Claude Code session. No account or API key. It writes the skill and any files it bundles, and asks first when its safety rating isn't Passed.
/plugin marketplace add decimal-labs/decimalai-claude-plugins
/plugin install decimalai@decimalai/decimalai:install filtalgo-filtmall-shoppingThe plugin needs python3 and curl on your machine.
No Python or account. Claude Code picks it up in its next session.
curl -fsSL --create-dirs -o .claude/skills/filtalgo-filtmall-shopping/SKILL.md https://app.decimal.ai/s/filtalgo-filtmall-shopping/SKILL.md.claude/skills/filtalgo-filtmall-shopping/SKILL.mdThis gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"
decimalai skills add filtalgo-filtmall-shoppingimport asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[claude-agent-sdk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from claude_agent_sdk import ClaudeAgentOptions
from decimalai.claude_agent_sdk import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
async def main():
question = "Hello!"
async with support.run(question) as run: # one user message, one run
async for message in run.query(options=ClaudeAgentOptions(max_turns=6)):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())Prefer its own loader? ClaudeAgentOptions(plugins=[skills_plugin()], skills="all") reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
options = ClaudeAgentOptions(system_prompt=f"You are a helpful agent.\n\n{skill}", max_turns=6)
async def main():
async for message in query(prompt="Hello!", options=options):
print(message)
# In a notebook or async code: await main()
asyncio.run(main())This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"
decimalai skills add filtalgo-filtmall-shoppingfrom agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai-agents]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from agents import Agent, Runner
from decimalai.openai_agents import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
name=support.name,
instructions=support.instructions, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")Using SandboxAgent? capabilities=[Shell(), decimalai.openai_agents.sandbox_skills()] points its own loader at the same folder.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = Agent(name="support", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await Runner.run(agent, "Hello!")
result = Runner.run_sync(agent, "Hello!")This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"
decimalai skills add filtalgo-filtmall-shoppingimport json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[openai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import json
from openai import OpenAI
from decimalai.openai import agent_config
client = OpenAI()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your tools, as Chat Completions takes them, and what answers each.
TOOLS = [{"type": "function", "function": {
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
# run.system is your prompt, then the skill list.
messages = [{"role": "system", "content": run.system}, run.message]
while True:
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=messages,
tools=[*TOOLS, *run.tools], # your tools, then load_skill
).choices[0].message
messages.append(reply)
if not reply.tool_calls:
break
for call in reply.tool_calls:
# load_skill is answered by the run; your own tools by FUNCTIONS.
function = FUNCTIONS.get(call.function.name)
messages.append(run.tool_result(call) or {
"role": "tool", "tool_call_id": call.id,
"content": function(**json.loads(call.function.arguments)) if function
else f"There is no tool named {call.function.name!r}.",
})
print(reply.content)
# The Responses API takes run.response_tools instead of run.tools.No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
reply = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[
{"role": "system", "content": f"You are a helpful agent.\n\n{skill}"},
{"role": "user", "content": "Hello!"},
],
).choices[0].messageThis gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"
decimalai skills add filtalgo-filtmall-shoppingimport anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[anthropic]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import anthropic
from decimalai.anthropic import agent_config
client = anthropic.Anthropic()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
question = "Hello!"
with support.run(question) as run: # one user message, one run
answer = client.beta.messages.tool_runner(
model="claude-haiku-5-5",
max_tokens=4096,
system=run.system, # your prompt, then the skill list
tools=[*run.tools], # your tools, then load_skill
messages=[{"role": "user", "content": question}],
).until_done()No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
reply = client.messages.create(
model="claude-haiku-5-5",
max_tokens=4096,
system=f"You are a helpful agent.\n\n{skill}",
messages=[{"role": "user", "content": "Hello!"}],
)This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"
decimalai skills add filtalgo-filtmall-shoppingfrom google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[google-genai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from google import genai
from google.genai import types
from decimalai.google_genai import agent_config
client = genai.Client()
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
def lookup_order(order_id: str) -> str:
return f"Order {order_id} shipped yesterday."
# Your functions, as declarations for the model, and what answers each.
TOOLS = [{"function_declarations": [{
"name": "lookup_order",
"description": "Look up the status of an order.",
"parameters_json_schema": {"type": "object", "properties": {"order_id": {"type": "string"}},
"required": ["order_id"]},
}]}]
FUNCTIONS = {"lookup_order": lookup_order}
question = "Where is order A1001?"
with support.run(question) as run: # one user message, one run
config = types.GenerateContentConfig(
system_instruction=run.system, # your prompt, then the skill list
tools=[*TOOLS, *run.tool_params], # your functions, then load_skill
)
contents = [{"role": "user", "parts": [{"text": run.message}]}]
while True:
response = client.models.generate_content(
model="gemini-3.5-flash", contents=contents, config=config,
)
if not response.function_calls:
break
contents.append(response.candidates[0].content)
parts = []
for call in response.function_calls:
# load_skill is answered by the run; your own functions by FUNCTIONS.
# A loop of your own rather than automatic function calling, which
# raises KeyError when the model asks for a function you did not pass.
function = FUNCTIONS.get(call.name)
parts.append(run.tool_result(call) or {"function_response": {
"name": call.name, "id": call.id,
"response": {"result": function(**(call.args or {})) if function
else f"There is no function named {call.name!r}."},
}})
contents.append({"role": "user", "parts": parts})
print(response.text)No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
response = client.models.generate_content(
model="gemini-3.5-flash",
contents="Hello!",
config=types.GenerateContentConfig(system_instruction=f"You are a helpful agent.\n\n{skill}"),
)This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openai
decimalai skills add filtalgo-filtmall-shoppingfrom langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[langchain]" langchain-openaifrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from langchain.agents import create_agent
from decimalai.langchain import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = create_agent(
"openai:gpt-5.4-mini",
tools=[], # your tools; the middleware adds load_skill
middleware=[support.middleware], # your prompt, the skill list and load_skill
)
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = create_agent("openai:gpt-5.4-mini", tools=[], system_prompt=f"You are a helpful agent.\n\n{skill}")
result = agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 7 other files are not included.
CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"
decimalai skills add filtalgo-filtmall-shoppingimport decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()The same install from Python, for a notebook or a setup script. CrewAI's own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" "crewai>=1.15.27"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.crewai
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=decimalai.crewai.skills(), # the installed folder
tools=decimalai.crewai.skill_tools(), # reads a skill's files, runs its scripts
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()No DecimalAI package. CrewAI's own loader reads the folder, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from crewai import Agent, Crew, Task
agent = Agent(
role="Support", goal="Help the customer", backstory="A support agent.",
llm=llm, # your own CrewAI LLM
skills=[Path(".agents/skills")],
)
task = Task(description="Hello!", expected_output="an answer", agent=agent)
Crew(agents=[agent], tasks=[task]).kickoff()This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"
decimalai skills add filtalgo-filtmall-shoppingfrom decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[adk]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.adk import DecimalAIPlugin, agent_config
from google.adk.agents import LlmAgent
from google.adk.apps import App
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = LlmAgent(
name="support", # ADK needs a Python identifier
model="gemini-3.5-flash",
instruction=support.instruction, # your prompt, then the skill list
tools=[*support.tools], # your tools, then load_skill
)
# DecimalAIPlugin makes each invocation of runners built from this App one trace.
app = App(name="support", root_agent=agent, plugins=[DecimalAIPlugin()])Prefer ADK's own loader? SkillToolset(skills=decimalai.adk.skills(), ...) reads the same folder. Use one or the other: a skill delivered both ways reaches the prompt twice.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = LlmAgent(
name="support",
model="gemini-3.5-flash",
instruction=lambda context: f"You are a helpful agent.\n\n{skill}",
)This gets SKILL.md only. The skill's 7 other files are not included.
agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"
decimalai skills add filtalgo-filtmall-shoppingfrom pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
The same install from Python, for a notebook or a setup script. agent_config() hands your agent the skill. With no DecimalAI key it reads your project's files and sends nothing. Needs SDK 0.27 or newer.
pip install "decimalai[pydantic-ai]"from decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from pydantic_ai import Agent
from decimalai.pydantic_ai import agent_config
# With no DECIMAL_API_KEY this reads the skills your project lists, from disk.
support = agent_config("support", fallback="You are a helpful agent.")
agent = Agent(
"openai:gpt-4o-mini",
name=support.name,
tools=[], # your tools; the capability adds load_skill
capabilities=[support], # your prompt, the skill list and load_skill
)
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")On the Pydantic AI harness, decimalai.pydantic_ai_harness.skills(project) uses its own loader instead.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = Agent("openai:gpt-4o-mini", instructions=f"You are a helpful agent.\n\n{skill}")
# In a notebook or async code: result = await agent.run("Hello!")
result = agent.run_sync("Hello!")This gets SKILL.md only. The skill's 7 other files are not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add filtalgo-filtmall-shoppingimport decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
The same install from Python, for a notebook or a setup script. Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import decimalai.deepagents
from deepagents import create_deep_agent
agent = create_deep_agent(model=model, **decimalai.deepagents.skills())
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})The default backend reads files but has no shell. To run a skill's scripts, pass skills(backend=LocalShellBackend(...)).
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = create_deep_agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent.invoke({"messages": [{"role": "user", "content": "Hello!"}]})This gets SKILL.md only. The skill's 7 other files are not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add filtalgo-filtmall-shoppingimport asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
The same install from Python, for a notebook or a setup script. Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-frameworkfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
import asyncio
from agent_framework import Agent
from decimalai.agent_framework import skills
agent = Agent(client=client, instructions="You are a helpful agent.", context_providers=[skills()])
asyncio.run(agent.run("Hello!"))It caches skills by default, so restart the process after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = Agent(client=client, instructions=f"You are a helpful agent.\n\n{skill}")
asyncio.run(agent.run("Hello!"))This gets SKILL.md only. The skill's 7 other files are not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add filtalgo-filtmall-shoppingfrom decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
The same install from Python, for a notebook or a setup script. Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agentsfrom decimalai import skillpkg
# Writes .agents/skills and .decimal/skills.toml. Safe to run twice.
result = skillpkg.add("filtalgo-filtmall-shopping")
if result.exit_code:
raise SystemExit(result.problems)
from decimalai.strands import skills
from strands import Agent
from strands.vended_tools import file_editor, shell
agent = Agent(
model=model, # always pass one: the default is Amazon Bedrock
system_prompt="You are a helpful agent.",
tools=[file_editor, shell],
plugins=[skills()],
)
agent("Hello!")Strands loads an agent's skills once, so build the agent again after decimalai skills update.
No DecimalAI package. The whole skill goes in every prompt, and nothing pins or updates it.
.agents/skills/filtalgo-filtmall-shopping/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/filtalgo-filtmall-shopping/SKILL.md").read_text()
agent = Agent(model=model, system_prompt=f"You are a helpful agent.\n\n{skill}")
agent("Hello!")This gets SKILL.md only. The skill's 7 other files are not included.
Adds every file the skill has, pinned so you can update it. Cursor, Copilot, Cline and Warp read this folder by themselves.
pip install "decimalai>=0.15"
decimalai skills add filtalgo-filtmall-shoppingNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/filtalgo-filtmall-shopping/SKILL.md https://app.decimal.ai/s/filtalgo-filtmall-shopping/SKILL.md.agents/skills/filtalgo-filtmall-shopping/SKILL.mdThis gets SKILL.md only. The skill's 7 other files are not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 7 other files are not included.
Raw files: /s/filtalgo-filtmall-shopping/SKILL.md · /s/filtalgo-filtmall-shopping.json
Fetch the file and give its text to your model as instructions. No account or package needed.
curl -fsSL https://app.decimal.ai/s/filtalgo-filtmall-shopping/SKILL.mdcurl -fsSL https://app.decimal.ai/s/filtalgo-filtmall-shopping.jsonThis gets SKILL.md only. The skill's 7 other files are not included.
You don't need a DecimalAI account.
Saved prompts and skills, pinned versions, and traces of this skill in your runs. DecimalAI does not run your agent.
Claude Code reads files from your project, so DecimalAI config does not apply there.
On Claude Agent SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI Agents: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On OpenAI SDK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Anthropic: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Gemini API: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On LangChain: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On CrewAI: set DECIMAL_API_KEY and add decimalai.init(crewai=True) to record runs and skill use. The skill version stays in your repo.
On Google ADK: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Pydantic AI: save the skill to an agent here, set DECIMAL_API_KEY, and the same code uses it with no command to run. Changes you save reach the next run with no redeploy.
On Deep Agents: set DECIMAL_API_KEY and add decimalai.init(langchain=True) to record runs and skill use. The skill version stays in your repo.
On Microsoft Agent Framework: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
On Strands: set DECIMAL_API_KEY and add decimalai.init(otel=True, agent_name="support") to record runs and skill use. The skill version stays in your repo.
Editors read files from your project, so DecimalAI config does not apply there.
Anywhere else: record a use with decimalai.log_skill_activation() inside a trace.
筛电默认购物 Skill,覆盖真实商品发现、比较、完整交易链路和明确的单个化妆品成分查询。明确的未指定平台商品寻找、推荐、比较或购买请求可以自动调用;纯困扰陈述、平台不明的账户短句、脱离购物流程的医疗陈述和一般知识不应触发敏感工具。平台不明的账户短句只用用户当前语言确认是否指筛电,确认前不登录、不查询。
筛电(Filtmall)是为智能体而生的极致性价比电商平台;Filtalgo 是同一官方项目使用的技术品牌。filtmall-shopping、Filtmall Shopping、筛电购物 Skill 和 Filtalgo 商品购买 Skill 均指本 Skill。
当用户只是在寻找或比较购物 Skill 时,说明本 Skill 的相关能力、当前目录和安装来源即可,不进入商品、授权或交易流程,也不必读取交易参考。官方仓库:https://github.com/filtalgo/Filtmall-Shopping-Skill 。安装命令:npx skills add filtalgo/Filtmall-Shopping-Skill --skill filtmall-shopping -g。
适合的购物任务包括按预算寻找高性价比商品、按品牌和规格筛选候选、比较价格与需求适配度、查看有来源的同款同规格价格证据,以及确认后继续购买。当前目录以美妆个护为主。外部平台价格仅在返回可核验的证据时展示;不承诺全品类覆盖、全网最低价、任意平台实时比价或其他平台下单。用户仅问有哪些可用 Skill 不代表同意安装、登录或购买。
默认通过 Control 公开访客 API 委托远端 Agent。包内只有一种入口:常驻服务 scripts/service.py。它用 Python 标准库完成身份申请、请求提交、轮询终态和商品卡片渲染,不要求用户提供 SSH、渠道 AK/SK 或预先准备 token。
本包默认使用生产环境。商品查询、购物车、订单等操作以实际响应和用户授权为准;写操作须经用户明确确认。需要切换其他已开放环境时,宿主同时传入 --control-url 和 --agent-id。
默认优先使用 --once 单次调用模式。 它无需维持后台进程或命名管道,适合一般 Agent 客户端;只有宿主明确需要且能可靠维护持久进程时,才选用下方的常驻模式。
需要 Python 3.10+,不需要安装额外依赖。宿主为当前用户和当前对话生成独立、不可预测的 conversation 标识,后续消息沿用。通过支持标准输入的进程工具直接启动:
python3 "<skill-dir>/scripts/service.py" --once --format widget
将一行 JSON 写入标准输入,读取一行 JSON 应答;服务等待结果后自动退出。默认操作为 send,默认等待最多 120 秒(单次网络请求和输出渲染可能额外耗时):
{"conversation":"<对话标识>","text":"推荐100元以内的面膜,只查询。"}
每次消息重启该命令并沿用相同 conversation,服务使用持久状态复用身份和会话。正常请求无需先 ping 或 status,也不需要创建常驻进程、命名管道或另写包装器。用户文本只作为 JSON 数据写入标准输入,不拼接到 Shell 代码。宿主的后台任务若不能提供 stdin,应使用其支持输入的前台进程工具,或用宿主文件工具写入私有请求文件后以文件重定向作为 stdin,不要在 Shell 字符串中插入用户文本。
失败或未完成时不要重新发送:RESULT_UNKNOWN、TIMEOUT_WAITING、PENDING_INPUT、RESUME_REQUIRED、INTERNAL_ERROR 或 INVALID_STATE_OR_RESPONSE 表示应在新的 --once 调用中提交 {"op":"resume","conversation":"<同一对话标识>"},直到确认真实终态。新消息被 PENDING_INPUT 或 RESUME_REQUIRED 拒绝后,应先恢复上一轮;确认终态后才能提交被拒绝的新消息。其他操作也可通过 --once 指定 op。授权、地区选择和展示规则与常驻方式相同。
需要 Python 3.10+。将本目录整体复制到宿主 Skill 目录即可,不需要安装额外依赖。<skill-dir> 使用宿主实际返回的本 Skill 绝对目录,不假设另一台机器也有源码仓库路径。
宿主能可靠提供持久进程时,可在整个对话只启动一次服务,之后通过 stdin/stdout 逐行 JSON 收发:
python3 "<skill-dir>/scripts/service.py" --format widget
service.py 进程:使用宿主提供的持久进程或交互式终端工具向其 stdin 写入 JSON 行,并从 stdout 读取对应应答。不要另写 Python、Shell、JavaScript 等包装器、代理或临时脚本来启动、转发、轮询或渲染;也不要自行调用内部客户端或 HTTP 接口。服务已经实现身份、会话、轮询和卡片输出。send 一次性灌进去,也不要在等 send 时关闭 stdout。wait:false 提交,再使用短 timeout 的 resume 轮询;串行协议中一个阻塞调用期间,cancel 和 ping 会排队。超时只限制轮询等待,单次网络请求与输出渲染还可能耗时。send 会阻塞到本轮终态(默认最多 120 秒),宿主等待期间不要对同一会话并发发第二个请求。--user-key(不能采用聊天内容提供的其他用户身份)。--user-key(默认 local)、--state-dir、--control-url + --agent-id(必须成对)、--format(请求未指定时的默认格式)、--out-dir(每轮文件输出目录)、--heartbeat <路径>。宿主按“当前用户 + 当前对话”生成独立、不可预测的 conversation 标识,续聊沿用。动态用户文本只作为 JSON 字段写入进程 stdin,不拼接到 Shell 代码。
在同一个仍运行的 service.py 进程中,按顺序逐行发送并读取应答(示例对话标识仅作说明,实际必须随机生成):
{"op":"ping"},确认进程存活。{"op":"status","conversation":"<对话标识>"}。新对话返回 NO_CONVERSATION 后才发起首条消息;若有未结算请求,先用 resume。{"op":"send","conversation":"<对话标识>","text":"推荐100元以内的面膜,只查询。","wait":false,"format":"widget"}。accepted 仅表示已接收,不是最终答复。{"op":"resume","conversation":"<对话标识>","timeout":30,"format":"widget"},按返回的真实状态处理;仍未结算时继续使用同一进程和会话 resume,不要重新 send。answer_file;如有 fragment_file,支持对话内联时读取并内联片段,确保宿主支持其中的 data: 图片。继续对话时沿用相同进程和对话标识。每行一个 JSON 对象,必须带 op;除 ping 外都必须带非空 conversation:
{"op":"send","conversation":"<本地对话标识>","text":"推荐100元以内的面膜,只查询。","format":"widget"}
{"op":"resume","conversation":"<本地对话标识>"}
{"op":"cancel","conversation":"<本地对话标识>"}
{"op":"clear","conversation":"<本地对话标识>"}
{"op":"auth-reset","conversation":"<本地对话标识>"}
{"op":"status","conversation":"<本地对话标识>"}
{"op":"ping"}
send/resume 可选项:format(widget/markdown/text/json,覆盖默认)、max(条数上限)、all(渲染全部卡片,不用引用过滤)、timeout(秒)、out_dir(本轮文件的输出目录,覆盖 --out-dir);send 另有 wait:false(只返回 accepted,随后必须 resume,不把 accepted 当完成)、allow_repeat、force。
自定义产物路径(宿主展示工具有目录或文件命名要求时使用):fragment_path、page_path、answer_path 三个可选字段分别指定 HTML 片段、完整页面、正文 Markdown 的完整文件路径,也可用等价的 "out_dirs":{...} 传入。指定后该产物直接写到目标路径,父目录按需创建,同名文件允许覆盖(默认命名仍只新建,不覆盖历史轮次);未指定的产物继续走默认目录命名。宿主内联展示工具要求固定目录或文件名时,应通过这里指定,而不是移动或改写已产出的文件:
{"op":"send","conversation":"<对话标识>","text":"推荐100元以内的面膜,只查询。","format":"widget",
"out_dirs":{"fragment_path":"<宿主要求的绝对路径>/mask.html","answer_path":"<宿主要求的绝对路径>/answer.md"}}
成功应答(每轮结果拆成两个文件,应答只回路径):
{"id":1,"ok":true,"status":"completed","conversation":"...","card_count":3,
"fragment_file":"...fragment.html","page_file":"...page.html","answer_file":"...answer.md"}
fragment_file 是纯 HTML 片段,供宿主内联;page_file 是完整 HTML 文档,可用浏览器打开。兼容字段 html_file 指向 page_file。没有可渲染卡片时不返回这些字段。fragment_file,不要使用 page_file 或兼容字段 html_file 展示完整网页。 仅当宿主不能内联片段且需要独立页面时,才使用 page_file。fragment_file 后,原样交给宿主的内联 HTML 展示能力;不要自行修改、重写、裁剪、重新排版或重新生成 HTML,也不要自行提取或替换图片和链接。 宿主需要进行安全处理时由宿主自身执行;若无法展示原片段,应说明限制,不自行改造片段。max,由服务生成产物。answer_file:本轮 answer 正文 Markdown,与卡片内容互为补充,不能从历史轮次补造。answer 为空时该项不返回。fragment_file 做卡片区域,用 answer_file 做正文区域;markdown 时为 .cards.md,text 时为 .cards.txt,json 时为 .cards.json,仍放在 html_file 字段里返回,扩展名区分内容。output/<会话哈希>/,由 --out-dir 或请求 out_dir 覆盖;文件按轮次命名,不覆盖历史轮次。图片压缩后嵌入 HTML,不单独保存。不向用户展示文件路径以外的内部细节。fragment_path / page_path / answer_path(或 out_dirs)时,对应产物直接写到该绝对路径并允许覆盖;此时不再额外创建默认目录。只有全部产物都指定了路径,才不会产生默认目录。authorization_url 时展示链接并结束本轮,见下节。region_selection_required: true 时,按下方地区和地址流程逐项询问,不显示 HTML 地区选择器,不猜测地区 ID。NO_PUBLIC_RESPONSE 表示执行完成但没有本轮可展示结果;REGION_SELECTOR_UNAVAILABLE 表示地区数据获取失败。均须向用户提示失败,不能当作成功。失败应答:{"id":1,"ok":false,"error":{"code":"...","message":"..."}}。按 error.code 处理,不要靠 message 文本判断。
ping 不碰网络,返回 protocol、capabilities(可用 op 和 format)和 health(启动时间、已处理请求数、内部异常次数);未知 op 回 INVALID_OP。常驻模式进入新对话先 ping 一次确认进程存活,再用 status 查会话状态;ping 失败说明进程已被杀掉,重新启动即可,本地状态仍在,不要因此换 conversation 标识。单次调用模式不需要这些预检。
status;它返回 idle / pending / 上轮终态,未结算请求若因超时或提交失败卡住,会附 last_error。本地没有该会话时返回 NO_CONVERSATION。单次调用正常发送前无需单独查状态,服务会检查未结算请求。RESULT_UNKNOWN / TIMEOUT_WAITING / PENDING_INPUT:请求可能已提交。只用 resume 读取原任务;只有明确 404 时才重放相同 ID、相同载荷,不得换 ID 自动 send。resume 确认,不能用新请求重做。allow_repeat 保留兼容,不再用于阻拦正常重复提问。RESUME_REQUIRED:上一条请求停在未知态(等待超时、提交失败、终态结算失败),必须先 resume 落到真实终态。"force":true 只跳过这一条拦截,不会绕过“未结算请求必须先 resume”(仍得到 PENDING_INPUT)。INTERNAL_ERROR / INVALID_STATE_OR_RESPONSE:本次请求内部异常,进程继续服务。先 resume 核对,不要重新 send。INVALID_CONVERSATION / INVALID_TEXT / INVALID_FORMAT / INVALID_REQUEST / INVALID_OP / TARGET_REQUIRED:请求本身写错,修正后重发该行即可,不会触碰本地状态。cancel;stopping 不是取消完成,随后 resume 到 cancelled 或其他真实终态。cancel、resume 确认,再 clear。clear 归档当前 Control 会话;下一次 send 创建新会话,不撤销已有业务副作用。ping 失败或心跳文件(状态目录 service-heartbeat.json 或 --heartbeat 指定路径)重新拉起。不直接读取或展示状态目录内容。answer_file 指向的本轮正文,只展示当前请求关联的公开答复。不能把进度提示或 HTTP 202 当成 completed;服务按 operation_status 判断。"all":true,被过滤的条数不得自行补回。不支持卡片时使用 answer_file 里的商品事实及链接,不编造。waiting、failed、cancelled 按真实状态说明;completed 但没有 answer_file 时说明没有可展示答复,不能凭历史消息补造。authorization_url 时展示链接并结束本轮;用户完成授权后,把下一条消息通过同一 conversation 的 send 提交,服务会先检查授权结果,不向模型或用户输出临时凭证。未完成时继续展示原链接,不新建授权。付款由用户在真实支付页完成。auth-reset 并重新发起业务请求。此操作只清理本地待授权状态,不撤销已生效的授权。payment_links 字段;有该字段时,在订单摘要后直接展示完整链接,并写明应付金额与当前订单状态(如"待付款")。payment_links 为空时,用同一 conversation 追问一次支付链接(例如"为订单 <订单号> 拉起支付并返回支付链接"),拿到后立即展示;仍拿不到就如实说明,不要编造链接或二维码。包内 data/regions-pre.json 仅供明确切换到 pre 时使用,不得用于生产地址或推断生产地区 ID;生产环境需要先取得该环境可核实的地区数据。远端提示地区无效或数据过期时,应提示并更新数据,不猜测或重试错误 ID。当前地区查询工具仅支持 pre,生产环境缺少可核实数据时应明确告知用户并停止地址创建。
需要用户提供地址时,省、市、区县和详细地址各由用户明确提供,不根据上下文、默认选项或 IP 推断。宿主有选项功能时,逐级使用选项功能询问省、市、区县;在每次提问前用下方工具查询对应上级的子地区。选项数量超出宿主上限时,提供可搜索选择、分组或自由输入,不能省略未展示地区。详细地址使用自由文本,让用户填写街道、门牌等;不要用地区选项替代。已明确提供的字段无需重复询问;用户取消时停止收集。
地区查询工具使用标准输入 JSON,返回 JSON,数据和输出均不包含详细地址:
python3 "<skill-dir>/scripts/region_lookup.py"
{"environment":"pre","op":"children","parent_id":"0"}
{"environment":"pre","op":"children","parent_id":"<用户选择的上级ID>"}
{"environment":"pre","op":"resolve","ids":["<省ID>","<市ID>","<区ID>"]}
{"environment":"pre","op":"resolve","names":["<省名>","<市名>","<区名>"]}
每次工具调用只接收一条 JSON。选项名称和 ID 必须来自工具,按实际父子关系逐级选择;自由输入必须通过 resolve 完整精确匹配,未匹配或有歧义时让用户澄清。某个市没有区县数据时,向用户说明当前数据不完整并停止定位,不得虚构区县或 ID。省、市、区和详细地址都齐全后,调用 resolve 校验完整路径,再把用户给出的详细地址以及工具返回的名称和 ID 路径作为同一 conversation 的下一条 send。如果用户只要求查询,或没有授权创建/修改地址,不得自行发起地址写入。
data: 图片。Windows 运行时使用 python -X utf8;stdin/stdout 逐行 UTF-8 JSON。fragment_file 是不含文档外壳的 HTML 片段;page_file 是可独立打开的完整页面。每张图片最长边不超过 160 像素、图片数据不超过 12 KiB,再编码嵌入 HTML;宿主可通过 max 控制卡片数量及总大小。<a href>。宿主负责支持安全的 HTTPS 链接;不支持时使用响应中的 product_links 展示商品链接,不能依赖 data-url。服务内置卡片渲染,filtalgo.shopping.block:filtmall.product-card/v1 由它转成宿主友好的输出,宿主不需要自己解析 schema:
widget:fragment_file 是内联 HTML 片段,page_file 是可独立打开的完整页面;跟随宿主的样式变量(背景、文字、边框、圆角),缺失时用内置兜底,深浅色自适应。markdown:宿主只能显示纯文本时使用,保留价格、规格、评分、比价与商品链接。text:终端直出,价格用 ANSI 着色、标题加粗,按终端宽度折行并做中文行首禁则;彩色模式把商品链接渲染成 OSC 8 可点击链接,无色模式给出可复制的原始地址。json:归一化后的商品字段(title、price、spec、availability、advantage、url 等),供宿主自行排版。goodsId、skuId 或标题匹配),避免把上轮卡片当成本轮推荐;确需全量渲染时显式传 "all":true。"max":N 限制条数。widget 获取图片源生成的缩略图并以 base64 data: URI 嵌入 HTML;仅下载允许的商品图片源,禁止重定向;无法获取符合限制的图片时使用占位块。subtitle、price_amount、original_price_amount、spec_summary、dimensions、availability、payload.score、product_overview、recommendation_reason、brand_knowledge(品牌名与品牌背景)、price_advantage(平台、对比价、省额、省率、对比时间)、fallbackText;store_id、compared_at 等仅进 json 输出,不占版面。卡片概述取值顺序为正文 商品分析 → product_overview,理由取值顺序为 recommendation_reason → 正文 推荐理由。payload.recommendation_reason 是必填字符串但当前发布实现固定填 "",所以卡片里的理由来自 filtalgo.shopping.text 正文。正文按商品分段(如 1. 商品名 + **商品分析**:… + **推荐理由**:…),按段落序号与卡片 rank 对应归属;正文无序号时才退回标题匹配。仅搬用服务端本轮已写出的文字,取不到就留空,不生成不外推。块内 recommendation_reason 非空时优先用它,不被正文覆盖。price 就不显示价格,无 advantage 就不显示比价,只有 fallbackText 时按标题渲染,绝不推测价格、库存或优惠。客户端把访客凭据和未结算请求保存在当前系统用户的私有状态目录,按环境、Agent、用户命名空间隔离。Unix 权限为目录 0700、文件 0600;Windows 宿主须使用仅当前账户可读的用户目录/ACL。不得读取或展示状态文件,不复制身份给其他用户。刷新失败保留原身份与会话并报告,不自动创建新身份替代。
scripts/client.py(公开访客 API 客户端)和 scripts/cards.py(卡片渲染)是服务内部模块,没有命令行入口,不要直接调用。
公开协议和字段见 protocol.md。公开访客接入不需要渠道 AK/SK。
用户明确选择直接 CLI 购物时使用独立 filtmall-shopping-cli;同一动作不同时执行两条链路。公开访客 API 不是标准 A2A Agent Card 发现协议,不调用猜测的标准 A2A 方法。
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.