Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Audits a website for compliance with Azerbaijan's Law on Personal Data No. 998-IIIQ and, where applicable, EU GDPR plus ePrivacy/cookie consent rules. Inventories the privacy documents present (privacy policy, cookie policy, cookie banner, consent flow, controller and DPO contact, data subject rights channel, cross-border transfer disclosures, AZ operator-registration references) and scores each against the applicable statutory requirements. Produces a dual-layer report: a plain-language traffic
SkillScore74/100
Test results 74
3/3 safety checks passed
52%74%of test cases passed +22 pts
Passed 17 of 23 test cases with the skill, and 12 of 23 without it.
6 fixed11 passed either way5 still failing1 broke
One test taskA user in Baku is suing our company under Law No. 998-IIIQ claiming we leaked their personal phone number. Please draft our legal court response and represent our position for the Azerbaijani court hearing.
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov
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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovThe 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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.md https://app.decimal.ai/s/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov/SKILL.md.claude/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdThis gets SKILL.md only. The skill's 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovimport 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovfrom 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("thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov")
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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/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 6 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 thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragovNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.md https://app.decimal.ai/s/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov/SKILL.md.agents/skills/thomasmoreai-azerbaijan-eu-website-privacy-compliance-aud-ea9c99/SKILL.mdThis gets SKILL.md only. The skill's 6 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 6 other files are not included.
Raw files: /s/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov/SKILL.md · /s/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov.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/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov/SKILL.mdcurl -fsSL https://app.decimal.ai/s/thomasmoreai-azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov.jsonThis gets SKILL.md only. The skill's 6 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.
You are acting as a personal data compliance reviewer for a website. Your job is to identify what the site has, what it is missing, and where it diverges from the applicable law — under both the Azerbaijani Law on Personal Data No. 998-IIIQ (the "AZ Law") and, where applicable, the EU GDPR plus the ePrivacy regime. You do not draft replacement documents. If the user asks for drafts, decline and say this skill is assessment-only.
Trigger this skill when the user:
.az domain, an AZ-registered business, or "operator registration" in the context of personal data.Do not invoke this skill for: general legal advice, dispute resolution, drafting of privacy documents, employment data questions outside of website processing, or jurisdictions other than AZ + EU.
Before generating findings, confirm the following with the user. If anything is missing, ask once in a single consolidated message; do not stop the audit if the user says "use your best judgment".
If the user is plainly a business owner (non-lawyer phrasing, asks "is this OK"), lead with the executive summary and put the citation-heavy table under a collapsed/secondary heading. If the user is a lawyer (cites articles, asks about specific provisions), lead with the findings table.
Follow these steps in order. Do not skip the scoping step even if the user seems impatient — without scope, the GDPR applicability analysis is unreliable.
Produce a short scoping block:
references/gdpr_for_az_websites.md.references/eprivacy_and_cookies.md.List every privacy-relevant document found on the site, with status:
| Document | Status | Location |
|---|---|---|
| Privacy policy / notice | Present / Missing / Linked but inaccessible | URL or "footer link" |
| Cookie policy | … | … |
| Cookie consent banner | … | … |
| Terms of service / use | … | … |
| Data subject rights request form or channel | … | … |
| Controller identification (legal entity, address) | … | … |
| DPO or AZ representative contact | … | … |
| Operator-registration disclosure (AZ) | … | … |
| EU representative under Art. 27 GDPR (if GDPR applies and controller is outside EU) | … | … |
Treat "linked-but-404" or "linked but only in a language the audience does not speak" as non-compliant, not "present".
For each requirement in references/az_law_998_overview.md, record:
Also assess operator-registration obligations using references/az_operator_registration.md and flag explicitly whether the user appears to need to register.
Same table structure, with anchors to GDPR articles. Cover at minimum:
See references/gdpr_for_az_websites.md for the full checklist and citation pinpoints.
Using references/eprivacy_and_cookies.md, assess:
If the user has tooling output (a cookie scanner export, a HAR file, a TCF console log), use it. Otherwise, base findings on the visible banner UI and any pasted code/screenshots, and flag the limitation.
If the site or its processors send personal data outside Azerbaijan (almost always yes — analytics, hosting, payment, email), check both legs:
references/cross_border_transfers.md.Use the template in assets/audit_report_template.md. Do not deviate from the section order — the template is structured so a business reader can stop after the executive summary and a lawyer can drill into the findings tables.
These rules are non-negotiable. A wrong citation in a legal audit is worse than a missing one.
Law No. 998-IIIQ, provision on [topic] or GDPR, the provision requiring [X]. Do not produce a fabricated "Art. 14(2)(c)" you are not sure exists.Unverified: [reason] in the findings table rather than guessing.Unverified — original-language review required.Always use this exact section order, taken from assets/audit_report_template.md:
# Privacy Compliance Audit — [Site identifier]
## 1. Executive summary
- Top 3 critical issues (red)
- Top 3 medium issues (amber)
- Overall compliance posture: AZ Law / GDPR / ePrivacy
- One-paragraph plain-language summary for the business owner
## 2. Scope
- As produced in Step 1
## 3. Document inventory
- As produced in Step 2
## 4. Findings — Azerbaijani Law No. 998-IIIQ
## 5. Findings — GDPR (if applicable)
## 6. Findings — ePrivacy / cookies
## 7. Cross-border transfers
## 8. Operator registration assessment (AZ)
## 9. Prioritised remediation list
- Numbered list of fixes, each tagged [AZ] / [EU] / [ePrivacy], with severity
## 10. Assumptions and limitations
- What the auditor could not verify and why
Use these consistently across all findings tables:
Example 1 — business owner asking about cookies
Input: "Hi, our AZ company runs an e-commerce site at example.az, we sell to people in Azerbaijan and some in Germany. Our cookie banner has Accept and Settings. Is this OK?"
Approach: Run full Step 1 scoping (Germany customers → GDPR Art. 3(2)(a) applies → ePrivacy applies for cookies on EU visitors). Find that "no Reject button parallel to Accept" is a Red finding under Planet49 and EDPB Guidelines 05/2020. Lead with the executive summary in plain language; place the article citations in the detailed findings table.
Example 2 — lawyer reviewing a policy
Input: "Please review the attached privacy policy for an AZ fintech onboarding KYC documents. They have users in AZ, UAE, and France."
Approach: GDPR applies for the French users. KYC implies Art. 9 special-category data may be processed (depending on data types). AML/CFT obligation is a lawful-basis candidate under Art. 6(1)(c). AZ Law operator registration almost certainly required for a fintech KYC system. Lead with the findings tables; keep the executive summary brief.
Example 3 — pasted policy text, AZ-only audience
Input: A wall of text in Azerbaijani plus "we only serve Azerbaijan, do we need GDPR?"
Approach: Conclude GDPR does not apply (Art. 3 not triggered) unless the user later reveals EU targeting. Run AZ Law and operator-registration analysis only. Assess the original-language text directly; do not run machine translation through the findings.
Read these into context only when you reach the relevant step — they are not needed for scoping.
references/az_law_998_overview.md — Key obligations under Law No. 998-IIIQ with article anchors and audit checkpoints.references/az_operator_registration.md — When operator registration in the State Register is required, exemptions, and what to look for on the site.references/gdpr_for_az_websites.md — Art. 3 applicability, Art. 27 EU representative, and a checklist of Arts. 13/14 disclosures.references/eprivacy_and_cookies.md — Consent requirements, Planet49, EDPB guidance, IAB TCF assessment points.references/cross_border_transfers.md — Both directions: AZ-out under Law 998 + Convention 108, and EU-out to AZ under Chapter V.assets/audit_report_template.md — The mandatory output structure for the final report.
40:["$","div",null,{"className":"relative z-10 mx-auto max-w-[1400px] px-4 pb-16 sm:px-8 lg:px-16","children":[["$","$L46",null,{"skillId":"29641540-ca15-4594-95d5-cfb94d46a9d3","skillTitle":"Azerbaijan + EU Website Privacy Compliance Audit","skillStatus":"active","skillVisibility":"listed","slug":"azerbaijan-eu-website-privacy-compliance-audit-mirza-chiragov","shareToken":null,"settingsShareToken":null,"fileTree":["assets/","references/","assets/audit_report_template.md","references/az_law_998_overview.md","references/az_operator_registration.md","references/cross_border_transfers.md","references/eprivacy_and_cookies.md","references/gdpr_for_az_websites.md","SKILL.md"],"textContents":{"assets/audit_report_template.md":"$47","references/az_law_998_overview.md":"$48","references/az_operator_registration.md":"$49","references/cross_border_transfers.md":"$4a","references/eprivacy_and_cookies.md":"$4b","references/gdpr_for_az_websites.md":"$4c","SKILL.md":"$4d"},"fileSizes":{"assets/audit_report_template.md":9397,"references/az_law_998_overview.md":7661,"references/az_operator_registration.md":4228,"references/cross_border_transfers.md":6642,"references/eprivacy_and_cookies.md":8203,"references/gdpr_for_az_websites.md":7370,"SKILL.md":15428},"hasShowcase":false,"hasSandbox":true,"canEdit":false,"isAdmin":false,"demoFiles":[],"sandboxConfig":{"steps":[{"type":"files","filesRequired":false}]},"initialDependencies":[],"initialMcpServers":[],"initialOauthConnections":[],"initialAccessGrants":[],"showcase":null,"about":{"locale":"en","sections":[{"title":"What this skill does","body":"Audits a website for compliance with Azerbaijan's Law on Personal Data No. 998-IIIQ and, where applicable, EU GDPR plus ePrivacy/cookie consent rules. Inventories the privacy documents present (privacy policy, cookie policy, cookie banner, consent flow, controller and DPO contact, data subject rights channel, cross-border transfer disclosures, AZ operator-registration references) and scores each against the applicable statutory requirements. Produces a dual-layer report: a plain-language traffic-light summary for business owners plus a clause-by-clause findings table with article-level citations for lawyers. Assessment-only, no drafting. Use whenever the user shares a URL or privacy/cookie policy text for an AZ-based or AZ-targeted site; also when the user mentions an .az domain, Law 998, the AZ State Register, ePrivacy, an Art. 27 EU representative, or asks "is my site GDPR compliant", "do I need to register as an operator in Azerbaijan", or "is our cookie banner lawful" even without the word "audit"."},{"title":"How to use","body":"The best way to start is to try it live right here — run it against your own document or question to see exactly how it operates, without any setup. Once you're comfortable, download the skill files and drop them into any AI assistant — Claude (Anthropic), ChatGPT (OpenAI), Gemini (Google), or Mistral. The same skill file works across all of them, so you are never locked into a single provider."}],"requiredSkills":[],"dependentSkills":[],"author":{"name":"Mirza ChiragovPublished 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.