Install any skill in seconds. Free to start, no credit card required.
Get Started Free →萤石开放平台云台设备控制技能。支持设备列表查询、设备状态查询、云台控制 (PTZ)、预置点管理等功能。
SkillScore84/100
Test results 84
3/3 safety checks passed
40%84%of test cases passed +44 pts
Passed 21 of 25 test cases with the skill, and 10 of 25 without it.
11 fixed10 passed either way4 still failing0 broke
One test taskWhat numerical direction parameter is passed to `ptz_start` for automatic PTZ control mode?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add leoyeai-ezviz-open-ptz-control
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("leoyeai-ezviz-open-ptz-control")
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 leoyeai-ezviz-open-ptz-controlThe 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/leoyeai-ezviz-open-ptz-control/SKILL.md https://app.decimal.ai/s/leoyeai-ezviz-open-ptz-control/SKILL.md.claude/skills/leoyeai-ezviz-open-ptz-control/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is 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 leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is not included.
Deep Agents' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" deepagents
decimalai skills add leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is not included.
Its own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" agent-framework
decimalai skills add leoyeai-ezviz-open-ptz-controlimport 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is not included.
Strands' own skill loader reads the installed folder. No DecimalAI account needed.
pip install "decimalai>=0.16" strands-agents
decimalai skills add leoyeai-ezviz-open-ptz-controlfrom 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("leoyeai-ezviz-open-ptz-control")
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/leoyeai-ezviz-open-ptz-control/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/leoyeai-ezviz-open-ptz-control/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 1 other file is 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 leoyeai-ezviz-open-ptz-controlNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/leoyeai-ezviz-open-ptz-control/SKILL.md https://app.decimal.ai/s/leoyeai-ezviz-open-ptz-control/SKILL.md.agents/skills/leoyeai-ezviz-open-ptz-control/SKILL.mdThis gets SKILL.md only. The skill's 1 other file is not included.
Give its text to your model as instructions. No account or package needed.
This gets SKILL.md only. The skill's 1 other file is not included.
Raw files: /s/leoyeai-ezviz-open-ptz-control/SKILL.md · /s/leoyeai-ezviz-open-ptz-control.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/leoyeai-ezviz-open-ptz-control/SKILL.mdcurl -fsSL https://app.decimal.ai/s/leoyeai-ezviz-open-ptz-control.jsonThis gets SKILL.md only. The skill's 1 other file is 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.
萤石开放平台云台设备控制,支持设备查询、云台控制、预置点管理等功能。
在使用此技能前,请完成以下安全检查:
| # | 检查项 | 状态 | 说明 |
|---|---|---|---|
| 1 | 凭证权限 | ⚠️ 必需 | 使用最小权限的 AppKey/AppSecret,不要用主账号凭证 |
| 2 | Token 缓存 | ⚠️ 注意 | Token 缓存在 /tmp/ezviz_global_token_cache/ (权限 600) |
| 3 | API 域名 | ✅ 已验证 | openai.ys7.com 是萤石官方 API 端点(openai = Open API,不是 AI) |
| 4 | 代码审查 | ✅ 推荐 | 审查 scripts/main.py 和 lib/token_manager.py |
凭证获取优先级(从高到低):
┌─────────────────────────────────────────────────────────────┐
│ 1. 环境变量 (最高优先级 - 推荐) │
│ ├─ EZVIZ_APP_KEY │
│ └─ EZVIZ_APP_SECRET │
│ ✅ 优点:不读取配置文件,完全隔离 │
├─────────────────────────────────────────────────────────────┤
│ 2. 命令行参数 (最低优先级) │
│ python3 main.py appKey appSecret <command> │
└─────────────────────────────────────────────────────────────┘
安全建议:
重要: openai.ys7.com 是萤石官方 API 域名(openai = Open API,不是人工智能)
# 验证 API 域名连通性
curl -I https://openai.ys7.com/api/lapp/token/get
# 验证 SSL 证书
curl -vI https://openai.ys7.com/api/lapp/token/get 2>&1 | grep -A5 "SSL certificate"
# 验证域名所有权
whois ys7.com
官方文档: https://open.ys7.com/
# 1. 使用环境变量(优先级最高,避免配置文件意外使用)
export EZVIZ_APP_KEY="your_dedicated_app_key"
export EZVIZ_APP_SECRET="your_dedicated_app_secret"
# 2. 高安全环境:禁用 Token 缓存
export EZVIZ_TOKEN_CACHE=0
# 3. 测试凭证(推荐先用测试账号)
# 登录 https://openai.ys7.com/ 创建专用应用,仅开通云台控制相关权限
技能按以下顺序获取凭证(优先级从高到低):
EZVIZ_APP_KEY, EZVIZ_APP_SECRET) ← 推荐pip install requests
export EZVIZ_APP_KEY="your_app_key"
export EZVIZ_APP_SECRET="your_app_secret"
可选环境变量:
export EZVIZ_TOKEN_CACHE="1" # Token 缓存:1=启用 (默认), 0=禁用
Token 缓存说明:
EZVIZ_TOKEN_CACHE=0 每次重新获取 Token/tmp/ezviz_global_token_cache/global_token_cache.json注意:
EZVIZ_ACCESS_TOKEN!技能会自动获取 Tokenpython3 {baseDir}/scripts/main.py
命令行参数:
# 查询设备列表
python3 {baseDir}/scripts/main.py appKey appSecret list
# 查询设备状态
python3 {baseDir}/scripts/main.py appKey appSecret status BF6985110
# 查询设备能力集
python3 {baseDir}/scripts/main.py appKey appSecret capacity BF6985110
# 云台控制(向上)
python3 {baseDir}/scripts/main.py appKey appSecret ptz_start BF6985110 1 0 1
# 停止云台
python3 {baseDir}/scripts/main.py appKey appSecret ptz_stop BF6985110 1
# 调用预置点
python3 {baseDir}/scripts/main.py appKey appSecret preset_move BF6985110 1 1
1. 获取 Token (appKey + appSecret → accessToken)
↓
2. 执行操作 (根据命令调用对应 API)
↓
3. 输出结果 (JSON + 控制台)
你不需要手动获取或配置 EZVIZ_ACCESS_TOKEN!
技能会自动处理 Token 的获取:
首次运行:
appKey + appSecret → 调用萤石 API → 获取 accessToken (有效期 7 天)
↓
保存到缓存文件(系统临时目录)
↓
后续运行:
检查缓存 Token 是否过期
├─ 未过期 → 直接使用缓存 Token ✅
└─ 已过期 → 重新获取新 Token
Token 管理特性:
EZVIZ_ACCESS_TOKEN 环境变量EZVIZ_TOKEN_CACHE=0 可禁用缓存(每次运行重新获取)======================================================================
Ezviz Open PTZ Control (萤石开放平台云台设备控制)
======================================================================
[Time] 2026-03-19 10:00:00
[INFO] Command: list
======================================================================
[Step 1] Getting access token...
======================================================================
[INFO] Using cached global token, expires: 2026-03-26 10:00:00
[SUCCESS] Using cached token, expires: 2026-03-26 10:00:00
======================================================================
[Step 2] Executing command...
======================================================================
[INFO] Calling API: https://openai.ys7.com/api/lapp/device/list
[SUCCESS] Device list retrieved
======================================================================
RESULT
======================================================================
Status: success
Total devices: 3
Devices:
- dev1 (Status: online)
- dev2 (Status: online)
- dev3 (Status: offline)
======================================================================
| 命令 | 功能 | API 文档 |
|---|---|---|
list | 查询设备列表 | https://openai.ys7.com/help/680 |
status [dev] | 查询设备状态 | https://openai.ys7.com/help/681 |
capacity [dev] | 查询设备能力集 | https://openai.ys7.com/help/683 |
ptz_start [dev] [ch] [dir] [spd] | 开始云台控制 | https://openai.ys7.com/help/690 |
ptz_stop [dev] [ch] | 停止云台控制 | https://openai.ys7.com/help/691 |
preset_add [dev] [ch] | 添加预置点 | https://openai.ys7.com/help/692 |
preset_move [dev] [ch] [idx] | 调用预置点 | https://openai.ys7.com/help/694 |
preset_clear [dev] [ch] [idx] | 清除预置点 | https://openai.ys7.com/help/693 |
mirror [dev] [ch] [cmd] | 镜像翻转 | https://openai.ys7.com/help/695 |
方向参数 (direction):
| 值 | 方向 | 值 | 方向 |
|---|---|---|---|
0 | 上 | 1 | 下 |
2 | 左 | 3 | 右 |
4 | 左上 | 5 | 左下 |
6 | 右上 | 7 | 右下 |
8 | 物理放大 | 9 | 物理缩小 |
10 | 调整近焦距 | 11 | 调整远焦距 |
16 | 自动控制 |
速度参数 (speed):
0 - 慢速1 - 适中(推荐)2 - 快速镜像命令 (command):
0 - 上下翻转1 - 左右翻转2 - 中心翻转| 接口 | URL | 文档 |
|---|---|---|
| 获取 Token | POST /api/lapp/token/get | https://openai.ys7.com/help/81 |
| 设备列表 | POST /api/lapp/device/list | https://openai.ys7.com/help/680 |
| 设备状态 | POST /api/lapp/device/info | https://openai.ys7.com/help/681 |
| 设备能力集 | POST /api/lapp/device/capacity | https://openai.ys7.com/help/683 |
| 云台启动 | POST /api/lapp/device/ptz/start | https://openai.ys7.com/help/690 |
| 云台停止 | POST /api/lapp/device/ptz/stop | https://openai.ys7.com/help/691 |
| 预置点管理 | POST /api/lapp/device/preset/* | https://openai.ys7.com/help/692 |
| 域名 | 用途 |
|---|---|
openai.ys7.com | 萤石开放平台 API(Token、云台控制) |
设备状态:
online - 设备在线offline - 设备离线error - 状态查询失败错误码:
200 - 操作成功10002 - accessToken 过期20007 - 设备不在线20008 - 设备响应超时60020 - 不支持该命令 (设备不支持此功能)ptz_start 启动,再调用 ptz_stop 停止⚠️ 设备支持: 不是所有设备都支持云台控制,请先确认设备能力集
⚠️ 权限要求: 需要设备控制权限,子账户需要 Permission: Config
⚠️ 操作谨慎: 云台控制会影响摄像头角度,请谨慎操作
⚠️ Token 安全: Token 会缓存到系统临时目录(自动管理),不写入日志,不发送到非萤石端点
默认行为:
/tmp/ezviz_global_token_cache/global_token_cache.json)为什么缓存 Token:
如果您不希望 Token 被持久化,可以通过以下方式禁用缓存:
方法 1: 环境变量
export EZVIZ_TOKEN_CACHE=0
python3 scripts/main.py ...
方法 2: 修改代码
from token_manager import get_cached_token
# 禁用缓存
token_result = get_cached_token(app_key, app_secret, use_cache=False)
| 系统 | 路径 |
|---|---|
| macOS | /var/folders/xx/xxxx/T/ezviz_global_token_cache/ |
| Linux | /tmp/ezviz_global_token_cache/ |
| Windows | C:\Users\{user}\AppData\Local\Temp\ezviz_global_token_cache\ |
查看缓存:
# macOS/Linux
ls -la /tmp/ezviz_global_token_cache/
cat /tmp/ezviz_global_token_cache/global_token_cache.json
# 清除缓存
rm -rf /tmp/ezviz_global_token_cache/
# 1. 验证缓存文件权限
ls -la /tmp/ezviz_global_token_cache/global_token_cache.json
# 应该显示:-rw------- (600)
# 2. 验证缓存内容
cat /tmp/ezviz_global_token_cache/global_token_cache.json | python3 -m json.tool
# 3. 验证禁用缓存
export EZVIZ_TOKEN_CACHE=0
python3 scripts/main.py ...
# 应该显示 "Getting access token from Ezviz API" 而不是 "Using cached global token"
# 推荐:使用 .env 文件(不要提交到版本控制)
echo "EZVIZ_APP_KEY=your_key" >> .env
echo "EZVIZ_APP_SECRET=your_secret" >> .env
chmod 600 .env
# 加载环境变量
source .env
如果您在共享计算机或高安全环境中使用:
export EZVIZ_TOKEN_CACHE=0 # 禁用缓存
python3 scripts/main.py ...
# 清除所有缓存的 Token
rm -rf /tmp/ezviz_global_token_cache/
# 验证 Python 语法
python3 -m py_compile scripts/main.py lib/token_manager.py
# 验证 AST(确保无截断)
python3 -c "import ast; ast.parse(open('scripts/main.py').read()); ast.parse(open('lib/token_manager.py').read()); print('✅ Code integrity verified')"
# 检查文件行数(应 > 300 行)
wc -l scripts/main.py lib/token_manager.py
根据安全审计建议,请在安装前完成以下检查:
scripts/main.py 和 lib/token_manager.pyopenai.ys7.com 是萤石官方端点(openai = Open API,不是 AI)python3 -m py_compile 检查语法,确认无截断/tmp/ezviz_global_token_cache/ 可接受EZVIZ_APP_KEY 等环境变量EZVIZ_TOKEN_CACHE=0wc -l 检查行数)| 场景 | 命令 | 说明 |
|---|---|---|
| 📋 查看设备 | list | 获取所有设备列表 |
| 🔍 检查状态 | status [dev] | 查看设备是否在线 |
| 🎮 云台控制 | ptz_start / ptz_stop | 调整摄像头角度 |
| 📍 保存位置 | preset_add | 保存当前位置为预置点 |
| 🎯 调用位置 | preset_move [idx] | 移动到预置点 |
| 🔄 镜像翻转 | mirror [cmd] | 翻转摄像头画面 |
为什么是 openai.ys7.com 而不是 open.ys7.com?
| 域名 | 用途 | 说明 |
|---|---|---|
openai.ys7.com | ✅ API 接口 | 萤石开放平台 API 专用域名(openai = Open API,不是人工智能) |
open.ys7.com | 🌐 官方网站 | 萤石开放平台 官网/文档 入口 |
官方文档: https://open.ys7.com/
安全提示:
openai.ys7.com 是萤石官方 API 域名| 日期 | 版本 | 变更 | 说明 |
|---|---|---|---|
| 2026-03-19 | 1.0.5 | 添加代码完整性验证 | 回应审核关切,添加语法验证和代码完整性检查 |
| 2026-03-19 | 1.0.5 | 添加 API 域名验证说明 | 明确 openai.ys7.com 是萤石官方 API(Open API) |
| 2026-03-19 | 1.0.5 | 完善安全审计清单 | 添加代码审查和完整性验证步骤 |
| 2026-03-19 | 1.0.4 | 参考设备抓图技能格式 | 统一 metadata 格式、安全警告、凭证优先级说明 |
| 2026-03-19 | 1.0.3 | 整合元数据到 SKILL.md | 移除单独文件,所有信息整合到 SKILL.md |
| 2026-03-19 | 1.0.2 | 添加 Token 缓存支持 | 使用全局 Token 管理器,与设备抓图技能一致 |
最后更新: 2026-03-19
版本: 1.0.5 (代码完整性验证版)
作者: EzvizOpenTeam
主页: https://openai.ys7.com/
许可证: MIT-0
Automatically, when a task matches. Use when: 需要控制萤石云台设备、调整摄像头角度、设置预置点。 ⚠️ 安全要求:必须设置 EZVIZ_APP_KEY 和 EZVIZ_APP_SECRET 环境变量,使用最小权限凭证。
Published skills whose descriptions closely match this one, with their headline benchmark lift.
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.