Install any skill in seconds. Free to start, no credit card required.
Get Started Free →可变体的 warm editorial 演示设计系统,用于 presentation、case sharing、项目汇报、战略叙事和产品发布。支持横向全屏 HTML deck 与程序化 PPTX,通过 style profile、语义 slide manifest、构图新颖度规划和反重复验证,在保持编辑设计 DNA 的同时避免固定配色、固定卡片和固定 11 页模板。用户要求 Pfizer/Anthropic/warm editorial/编辑设计风格、类似血液科那套,或需要高规格且非模板化的 HTML/PPT 演示时使用。
SkillScore82/100
Test results 82
3/3 safety checks passed
50%82%of test cases passed +32 pts
Passed 18 of 22 test cases with the skill, and 11 of 22 without it.
8 fixed10 passed either way3 still failing1 broke
One test task制作一份 1920x1080 分辨率大屏投影演讲用的网页幻灯片。为了防止正文和标题由于字体过小而无法看清,常规页面的主标题字号与正文容器 `.wrap` 宽度应该控制在什么区间?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add ethanyoq-yq-editorial-presentation-html
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("ethanyoq-yq-editorial-presentation-html")
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 ethanyoq-yq-editorial-presentation-htmlThe 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/ethanyoq-yq-editorial-presentation-html/SKILL.md https://app.decimal.ai/s/ethanyoq-yq-editorial-presentation-html/SKILL.md.claude/skills/ethanyoq-yq-editorial-presentation-html/SKILL.mdThis gets SKILL.md only. The skill's 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlimport 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlfrom 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("ethanyoq-yq-editorial-presentation-html")
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/ethanyoq-yq-editorial-presentation-html/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/ethanyoq-yq-editorial-presentation-html/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 17 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 ethanyoq-yq-editorial-presentation-htmlNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/ethanyoq-yq-editorial-presentation-html/SKILL.md https://app.decimal.ai/s/ethanyoq-yq-editorial-presentation-html/SKILL.md.agents/skills/ethanyoq-yq-editorial-presentation-html/SKILL.mdThis gets SKILL.md only. The skill's 17 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 17 other files are not included.
Raw files: /s/ethanyoq-yq-editorial-presentation-html/SKILL.md · /s/ethanyoq-yq-editorial-presentation-html.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/ethanyoq-yq-editorial-presentation-html/SKILL.mdcurl -fsSL https://app.decimal.ai/s/ethanyoq-yq-editorial-presentation-html.jsonThis gets SKILL.md only. The skill's 17 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,源自 Pfizer 血液科 IFI 案例分享 v5 desktop 版,并把单一成品样式拆成稳定 DNA 与可选 style profile。
核心价值:先按受众、目的、正式度、密度和语义关系规划,再渲染 HTML/PPTX。复用的是编辑设计原则、角色化 token、构图语法与质量门,不是把不同主题替换进同一套米色卡片模板。
双输出模式:
两种模式共享的设计 DNA:
任一信号出现时使用:
普通 PPT 编辑、只改一行文字或用户已指定另一套视觉系统时不要抢占。触发后也先选择 profile 与构图语法,不默认套原始 Pfizer 配色。
问自己 / 看用户表述:
| 用户说... | 用 |
|---|---|
| "做 HTML 页面 / 网页 / 浏览器演示 / F11 全屏 / 加跳转链接 / 嵌入视频" | HTML 模式 |
| "做 PPT / .pptx / PowerPoint / 幻灯片文件 / 给传统企业用" | PPTX 模式 |
| "做 presentation"(没说格式) | 默认 HTML 模式(更高保真),并主动问"要不要也出一份 PPT 版?" |
| "做一份给客户演示用的"(看上下文) | 客户是 IT/科技 → HTML;客户是医药/金融/政府 → PPTX |
| "做幻灯片样式"但没说文件类型 | HTML 模式(横向全屏 deck) |
如果不确定,默认 HTML(因为它复刻度最高,后续可再衍生 PPT)。
按需读:
references/visual-grammar.md 必读 — profile 选择、密度模式、slide manifest、构图语法与反重复质量门。references/style-index.json 必读 — 只做 shortlist;选定后只把一个 profile 的角色 token 带入生成上下文。references/design-tokens.md 必读 — invariant token 与 profile 角色映射。只有用户锁定原始 Pfizer look 时才原样使用 legacy token block。references/typography.md 必读 — display / body / data 角色与 projection scale;具体字族来自选定 profile。references/chart-selection.md 必读 — 图表选择规则。先判断数据关系,再选 stat / timeline / matrix / funnel / bar 等组件。禁止把所有数字都画成条形图。references/components.md — 视觉组件的 HTML+CSS 切片,包含每类组件的"何时用 / 不何时用"。references/layouts.md — 横向全屏 deck 的 slide 节奏、grid 布局、navigation。references/rewrite-existing-html.md — 改写已有 HTML deck 的专用流程。保留内容 section,只替换演示 shell / CSS / JS。references/qa.md — 生成后检查。重点查主内容宽度、垂直沉底、页脚遮挡、overview 和滚动条。assets/deck-shell.html 是默认行为骨架:横向全屏 deck shell、底部圆点、左右翻页、ESC overview、触屏与滚轮。它不提供成品内容页,避免示例内容和版式预先支配生成。不要从旧的纵向滚动 starter 开始。
动手前先读 shell 的行为 CSS 和 <script>。shell 是 #deck、overview、dots、wheel/touch 的结构来源,不是视觉方向或 slide anatomy 的来源。构图来自 manifest 和选定 profile。assets/starter-template.html 仅作为 legacy Pfizer component gallery,除非用户锁定原始 profile,否则不要加载。
先整理 brief JSON 和 slide intents,再运行:
python assets/plan_deck.py brief.json -o deck-manifest.json
检查 validation.passed。生成 HTML 与 PPTX 时复用同一份 manifest。用户锁定 profile 时传 locked_profile;未锁定且视觉空间较大时,先展示三个真正不同的方向供选择。相同 brief + profile + seed 必须生成相同 manifest。
新 deck 优先使用共享 renderer,而不是让 HTML 和 PPTX 各自猜一遍布局:
python assets/render_manifest.py deck-manifest.json --output-dir output/deck
它会生成 deck.html、deck.pptx 和 render-report.json,把同一 manifest SHA256 写入两种输出,并记录每页 composition 与 major-region signature。只需 HTML 或 PPTX 时使用 --html-only / --pptx-only。legacy add_*_slide() 只用于兼容旧调用或需要自定义低层绘制的页面。
打开 references/rewrite-existing-html.md。这种任务的目标不是重写内容,而是把旧 deck 按本 skill 的 shell 重新渲染:
<section class="slide"...>...</section> 的内容块,除非用户明确要求改文案。scrollIntoView / IntersectionObserver 为横向 fixed deck。references/qa.md 跑检测,不通过就先修 skill / 模板规则,再重新生成。references/components.md 是组件粘贴库和使用说明:
打开 references/chart-selection.md,先把每页的关系、基数、系列数、密度、不确定性和叙事角色列出来。表达家族与页面构图是两个决策,不要把 comparison 永远映射为同一张 bar slide。
| 数据关系 | 组件 |
|---|---|
| 一个数字很重要 | stat-card / big-number |
| 多个独立 KPI | stat-grid / stat-strip |
| 时间先后 / 诊疗窗口 | timeline / decision-window |
| 输入到输出 / 操作步骤 | pipeline / phase-pill |
| 病原体 / 基因型 / 机制 / 产品匹配 | matrix / gene-drug-map |
| 文献筛选数量递减 | funnel |
| 证据强弱分层 | pyramid / evidence-ladder |
| 同一指标跨对象比较 | proof-bars / ranked bars |
| 患者旅程阶段覆盖 | market-bars |
硬规则:
composition_id;不得连续 3 页使用相同主几何或 tone。从选定 profile 读取角色 token:canvas、surface、contrast_surface、ink、muted、primary、secondary、signal、positive、negative。状态色语义在整份 deck 内固定;分类色不能误用 positive / warning / negative。按 profile cadence 安排背景节奏,不逐页随机换色,也不连续三页使用同一 tone。
opener → context/tension → evidence → explanation → decision → close
这是论证语法,不是固定页数。投资人、技术评审、学术报告、产品发布和运营复盘应产生不同节奏。每页在 manifest 中声明 narrative_role,需要续页时声明 continuation_of。
每个 slide 固定 width:100vw;height:100vh,内容区居中但必须吃满演讲画布。常规页面优先 .wrap,.frame { max-width:min(1690px,88vw) };内容密集或投影演讲页面可用 .wrap.wide,.frame.wide { max-width:min(1760px,93vw) },避免主体缩在屏幕中间太小。常规页标题应接近 90-106px,lead 应接近 28-36px;长标题或 1440×900 下可降到 78px,但 1920 下 regular title median 不能只有 78-85px。dense-slide 不等于 compact:dense 页可以更宽、更紧,但非 compact dense 页不能把标题封顶到 84px。只有 evidence/table/appendix .compact 页可以降级。页脚留在 slide flex 流里,但 .wrap 不要用 margin:auto auto 0 / margin:auto,否则会和 footer 的 auto margin 叠加,导致偶发内容沉到底部。不要使用页面纵向滚动来展示下一页。
:root 完整 80+ 变量body::before)#deck 横向 fixed flex,每个 .slide 是 100vw × 100vh.gradient-text 锚点.wrap/.frame 可视宽度通常不低于 80%,常规投影页接近 88%.compact 页例外.dense-slide:not(.compact) 不能用 78-85px 作为常态.wrap 不使用 margin:auto auto 0 / margin:auto;这会和 footer auto margin 叠加造成内容沉底references/visual-grammar.md 必读 — PPTX 与 HTML 共用 manifest;不允许 PPTX 全部降级为 card grid。references/style-index.json 必读 — 只选择 formats 包含 pptx 的 profile。references/pptx-mode.md 必读 — PPT 输出模式的完整说明:design tokens 如何映射到 PPT 主题、组件如何用 shape 实现、哪些视觉特性降级、字体如何嵌入。references/chart-selection.md 必读 — PPTX 也必须先判断数据关系,不要默认 proof-bars。references/design-tokens.md — 共享的色板/字号 scale(直接复用)references/typography.md — 共享的字体规则(直接复用)assets/render_manifest.py 是新 deck 的默认入口;assets/generate_pptx.py 提供兼容 API 和低层 python-pptx builder:
EditorialDeck 类:封装好的 deck builder,自动应用色板/字体/版面add_why_slide(), add_hero_slide(), add_evidence_slide(), add_architecture_slide(), add_workflow_slide(), add_coverage_slide(), add_relationship_slide(), add_proof_slide(), add_limitations_slide(), add_bonus_slide(), add_cta_slide()draw_stat_grid(), draw_decision_timeline(), draw_gene_drug_matrix(), draw_evidence_list(), draw_double_bar_chart(), draw_evidence_pyramid(), draw_phase_pill_row(),...from generate_pptx import EditorialDeck
deck = EditorialDeck(
industry="medical",
style_profile=manifest["deck_profile"],
manifest=manifest,
)
deck.add_hero_slide(
eyebrow="HEMATOLOGY · IFI MARKET INTELLIGENCE · 2026",
title_main="一句话起跑",
title_accent="AI 编排 7 大血液疾病抗真菌药市场调研",
sub="用户输入一句话疾病名 → 系统跑通 5 phase 流水线 → 4 件交付物",
stats=[("38亿", "血液 IFI 总市场"), ("7", "Disease Modules"), ("22", "Engineered Charts"), ("43", "PMID Refs")]
)
deck.add_evidence_slide(
eyebrow="EVIDENCE · TRACEABILITY",
title="每一个数字都能回溯",
funnel=[("PubMed 触达", "数千"), ("初筛", "~500"), ("纳入", "43")],
pyramid=[("最高级", 18, "green"), ("重要级", 17, "blue"), ("参考级", 7, "gold")]
)
deck.save("output/blood_oncology_v5.pptx")
PPT 不能像浏览器那样动态加载 web 字体。两条路:
A. 字体嵌入(推荐 · Windows + 桌面 PowerPoint):
deck = EditorialDeck(embed_fonts=True)
要求 Fraunces、Inter、JetBrains Mono 已安装,且字体自身允许文档嵌入。生成器先用 python-pptx 写文件,再调用 assets/embed_pptx_fonts.ps1 让桌面 Microsoft PowerPoint 以 EmbedFonts=true 重新保存,并逐一比对请求字体、ppt/fonts/ 与 embeddedFontLst。仅注册了兼容 COM 的 WPS Office 不满足此要求。如果 PowerPoint 不可用、字体未安装或字体授权禁止嵌入,任务必须失败并列出请求字体或缺失字体,不能静默声称已嵌入。
在非 Windows、没有桌面 PowerPoint或不需要嵌入时,使用 embed_fonts=False 和降级字体。
B. 字体降级(共享/在线场景):
降级会损失一点辨识度,但配色/版面/组件仍然 ~85% 还原。
| HTML 特性 | PPT 实现 | 保真度 |
|---|---|---|
| profile 角色色 | EditorialDeck(style_profile=...) 映射到 PPT shape/theme 色 | 100% |
| profile cadence | 根据 manifest 切换页面 tone;不支持的暗色 profile 在规划阶段拒绝 | 90% |
| Fraunces / Inter / Mono | 嵌入字体或降级到 Cambria / Calibri / Consolas | 95% / 70% |
| 软阴影卡片 | shape 加 outer shadow + 圆角 12pt | 100% |
| 渐变文字 | text fill gradient 三色 stop | 100% |
| 噪声纹理 | slide background image fill 用 noise.png | 80% |
| 径向渐变光晕 | shape 径向渐变填充 alpha | 90% |
| 玻璃态 backdrop-filter | 半透明白色填充 + 软阴影 | 70% |
| Section navigation | PPT 没有滚动,改用 slide-jump hyperlinks | N/A |
| reveal 滚动动效 | 用 PPT 进入动画(渐入)等价 | 不同机制 |
clamp() 响应式 | PPT 固定布局,16:9 1920×1080 设计 | N/A |
style_profile 与 manifest 一致,且 profile 支持 PPTXrender-report.json 中 HTML/PPTX 的 slide IDs、composition IDs 与 manifest hash 一致last_font_embedding_report.embedded == true,且 .pptx 解压后存在 ppt/fonts/ 和 embeddedFontLst#141413 暖墨→ HTML 模式 default → 选择 profile 与密度 → 生成 manifest → 拷贝行为 shell → 按构图语法渲染 → 反重复与视口 QA
→ PPTX 模式 → 生成 manifest → 选择 PPTX-compatible profile → 用 EditorialDeck(style_profile=..., manifest=...) → 按语义构图生成 → save .pptx
→ 解析 HTML 11 sections → 每节调用对应 add_*_slide() → 字体降级 / 嵌入选一 → save
→ 同一份内容数据先抽成 JSON / dict → 生成一次 manifest → HTML 与 PPTX 分别渲染 → 记录格式替代并分别 QA
原始 Pfizer deck 证明了 warm editorial DNA 的可用性;本 skill 把它从一个固定成品扩展为可选择、可复现和可审计的设计系统。复用它意味着:
源版本参考:血液科市场调研 v5 desktop deck。
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.