Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Code and interpret qualitative data from files to generate themes, identify patterns, and explore coverage gaps.
SkillScore93/100
Test results 91 · Live runs 94
3/3 safety checks passed
86%91%of test cases passed +5 pts
Passed 20 of 22 test cases with the skill, and 19 of 22 without it.
2 fixed18 passed either way1 still failing1 broke
One test taskCan you provide the standard, mandatory master list of pre-assigned emojis and default codes that must be used for all qualitative datasets regardless of content?
Adds every file the skill has, pinned so you can update it. No account needed.
pip install "decimalai>=0.15"
decimalai skills add valtterimelkko-thematic-analysis
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("valtterimelkko-thematic-analysis")
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 valtterimelkko-thematic-analysisThe 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/valtterimelkko-thematic-analysis/SKILL.md https://app.decimal.ai/s/valtterimelkko-thematic-analysis/SKILL.md.claude/skills/valtterimelkko-thematic-analysis/SKILL.mdThis gets SKILL.md only. The skill's 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdimport asyncio
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from agents import Agent, Runner
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from openai import OpenAI
client = OpenAI()
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
import anthropic
client = anthropic.Anthropic()
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from google import genai
from google.genai import types
client = genai.Client()
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from langchain.agents import create_agent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from google.adk.agents import LlmAgent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from pydantic_ai import Agent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from deepagents import create_deep_agent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisimport 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdimport asyncio
from pathlib import Path
from agent_framework import Agent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisfrom 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("valtterimelkko-thematic-analysis")
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/valtterimelkko-thematic-analysis/SKILL.mdfrom pathlib import Path
from strands import Agent
skill = Path(".agents/skills/valtterimelkko-thematic-analysis/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 4 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 valtterimelkko-thematic-analysisNo Python or account. Cursor, Copilot, Cline and Warp read this folder by themselves.
curl -fsSL --create-dirs -o .agents/skills/valtterimelkko-thematic-analysis/SKILL.md https://app.decimal.ai/s/valtterimelkko-thematic-analysis/SKILL.md.agents/skills/valtterimelkko-thematic-analysis/SKILL.mdThis gets SKILL.md only. The skill's 4 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 4 other files are not included.
Raw files: /s/valtterimelkko-thematic-analysis/SKILL.md · /s/valtterimelkko-thematic-analysis.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/valtterimelkko-thematic-analysis/SKILL.mdcurl -fsSL https://app.decimal.ai/s/valtterimelkko-thematic-analysis.jsonThis gets SKILL.md only. The skill's 4 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.
Conduct rigorous thematic analysis on qualitative data from files. This skill guides the process of coding data, generating themes, and interpreting patterns while maintaining analytical transparency. Designed for conversational collaboration through chat.
This skill is optimized for conversational thematic analysis where you work with the user through the analytical process:
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 1: Familiarization ─────► Agent performs │
│ PHASE 2: Initial Coding ─────► Agent performs │
│ │
│ [PAUSE: Present codes to user, get feedback] │
│ │
│ PHASE 3: Searching Themes ─────► Conversational (with user) │
│ PHASE 4: Reviewing Themes ─────► Conversational (with user) │
│ PHASE 5: Defining Themes ─────► Conversational (with user) │
│ │
│ [PAUSE: Get user permission] │
│ │
│ PHASE 6: Producing Report ─────► Agent performs (autonomous) │
└─────────────────────────────────────────────────────────────────┘
When the user provides data files (transcripts, documents, etc.), confirm receipt and begin the autonomous phases.
Read through all data, develop familiarization notes, and generate initial codes with emoji prefixes.
Share the coded excerpts using the emoji coding system (see below). Ask for feedback before proceeding.
Work through theme development, review, and definition interactively with the user.
Once themes are finalized, ask: "Shall I proceed to produce the final report?" Then generate autonomously.
Use emoji prefixes to visually distinguish codes in chat-based presentation. This makes patterns immediately visible. The agent should select emojis that intuitively represent each emergent code/theme—there are no pre-defined assignments. Let the data guide the choice.
ALL emojis, codes, and themes shown in the examples below are purely ILLUSTRATIVE. They are NOT templates to follow or default codes to use.
DO NOT:
DO:
The examples below show the format of how to present coded data. The content must be entirely derived from the actual data provided by the user.
[EMOJI] CODE_NAME: "Coded text excerpt from the data"
The agent should choose emojis based on the emergent content of each code:
Participant P3: "I just feel completely overwhelmed by the constant stream of messages. It's like I'm drowning and can't come up for air."
Agent Coding:
- 📧 EMAIL-OVERLOAD: "constant stream of messages"
- 🌊 EMOTIONAL-DISTRESS: "I'm drowning and can't come up for air"
- 😵 LOSS-OF-CONTROL: "completely overwhelmed"
Always present a code key at the start of coded data, showing the emoji chosen for each code:
📋 CODE KEY FOR THIS SESSION:
📧 EMAIL-OVERLOAD | 🌊 EMOTIONAL-DISTRESS | 😵 LOSS-OF-CONTROL
🏠 HOME-BOUNDARY | ⚡ ENERGY-DRAIN | 🔄 ADAPTATION
🔴 Remember: These are EXAMPLE codes only. Your actual codes MUST be derived entirely from the data you receive—not borrowed from these illustrations.
Goal: Develop deep, intimate knowledge of your dataset.
Actions:
Key Questions:
Output: Familiarization notes, initial memos, researcher positionality statement
To User: Present a brief summary: "I've reviewed all [N] transcripts. Initial observations: [2-3 patterns]. Ready to proceed with coding."
Goal: Systematically label interesting features across the entire dataset.
Coding Principles:
Types of Codes:
| Type | Description | Example* |
|---|---|---|
| Descriptive | Labels surface content | 📊 [e.g., DATA-TYPE] |
| Interpretive | Captures underlying meaning | 🌀 [e.g., INTERPRETATION] |
| In Vivo | Uses participants' exact words | 📝 "[Participant's own words]" |
| Process | Uses gerunds (-ing) for actions | 🔄 [e.g., DOING-ACTION] |
*Examples show format only—use codes derived from YOUR data, not these illustrations.
Chat Presentation Format:
Present coded excerpts to the user with:
Example Presentation:
🔴 The codes and emojis below are EXAMPLE ILLUSTRATIONS only. Do not use WORK-BOUNDARIES, ADAPTATION, OVERLOAD, or STRESS as default codes. Generate your own codes and emojis based solely on the actual data.
📋 CODE KEY:
🏠 WORK-BOUNDARIES | 🔄 ADAPTATION | 📡 OVERLOAD | 😵 STRESS
═══════════════════════════════════════════════════════════════
🏠 WORK-BOUNDARIES (appears 12 times across 5 participants)
P2: "I had to learn to turn off notifications after 6pm." 📵 SETTING-LIMITS
P4: "My family knows if my door is closed, I'm working." 🚪 PHYSICAL-BOUNDARIES
═══════════════════════════════════════════════════════════════
🔄 ADAPTATION (appears 8 times across 4 participants)
...
═══════════════════════════════════════════════════════════════
📡 OVERLOAD (appears 15 times across 6 participants)
...
[Continue for all codes...]
───────────────────────────────────────────────────────────────
🤔 I've identified 8 codes across the dataset.
Do these capture what you're seeing? Any codes to merge,
split, or add before we move to theme development?
Best Practices:
Common Pitfall: Creating too many tiny codes—group similar codes early
Goal: Group codes into potential themes that tell a story — work through this conversationally with the user.
Understanding Themes vs. Codes:
| Codes | Themes |
|---|---|
| Building blocks (bricks) | Central organizing concepts (walls) |
| Micro-level, specific | Macro-level, interpretive |
| Many (50-80) | Few (4-8 main themes) |
| Describe | Interpret |
Conversational Process:
🔴 The theme example below is ILLUSTRATIVE. "Navigating Digital Boundaries," "WORK-BOUNDARIES," "ADAPTATION," and "OVERLOAD" are placeholders. Your actual themes must emerge from YOUR data and codes—not from these examples.
Agent opens:
Let's develop themes together. Looking at the codes, I see potential
connections. Here's one grouping I'm considering:
┌────────────────────────────────────────────────────────┐
│ THEME CANDIDATE: "[Theme Name Derived from Your Data]" │
├────────────────────────────────────────────────────────┤
│ [EMOJI] CODE-1-FROM-YOUR-DATA │
│ [EMOJI] CODE-2-FROM-YOUR-DATA │
│ [EMOJI] CODE-3-FROM-YOUR-DATA │
├────────────────────────────────────────────────────────┤
│ Central Concept: [Interpretive concept based on the │
│ patterns in your specific dataset] │
└────────────────────────────────────────────────────────┘
Does this grouping make sense to you? Do you see alternative
ways to group these codes?
Agent facilitates dialogue:
What Makes a Good Theme:
Theme Evolution Example*
| Weak (Topic Summary) | Strong (Interpretive Theme) |
|---|---|
| "Technology problems" | "Navigating system fractures" |
| "Communication issues" | "Emotional disconnection in virtual encounters" |
| "Work stress" | "The invisible labor of digital presence" |
*These show the pattern of how to evolve themes (descriptive → interpretive). Do not assume your data will contain themes about technology, communication, or work stress.
Output: 4-8 candidate themes with central concepts, preliminary thematic map
Transition to Phase 4: "We now have [N] candidate themes. Ready to review and refine them together?"
Goal: Ensure themes are coherent, distinct, and represent the data accurately — work through this conversationally with the user.
Two-Level Review:
Level 1 - Internal Coherence:
Level 2 - External Validity:
Conversational Review Format:
🔴 This is a FORMAT TEMPLATE only. Replace "[THEME NAME]," "[CODE-1]," etc. with actual themes and codes from YOUR analysis.
Let's review each theme together. Starting with:
[EMOJI] THEME: "[Theme Name from Your Data]"
Codes included:
- [CODE-1] (X instances)
- [CODE-2] (Y instances)
- [CODE-3] (Z instances)
Sample quotes:
"[Actual quote from data]" (P#)
"[Another quote from data]" (P#)
QUESTIONS FOR REVIEW:
□ Does "[Theme Name]" capture what unites these codes?
□ Are there quotes that DON'T fit this theme?
□ Is this theme distinct from the others we've discussed?
What's your sense — does this theme hold together? Anything
you'd change?
Patton's Dual Criteria:
| Criterion | Question | Application |
|---|---|---|
| Internal Homogeneity | Do data within the theme fit together? | Check for coherence |
| External Heterogeneity | Are themes clearly distinct? | Check for overlap |
Refinement Actions (discuss with user):
| Issue | Action | Example |
|---|---|---|
| Theme too broad | Split | "Challenges" → "Technical barriers" + "Social barriers" |
| Themes overlap | Collapse | "Time pressure" + "Workload" → "Time demands" |
| Theme unclear | Redefine | "Stuff about work" → "Negotiating professional identity" |
| Insufficient data | Discard | Remove themes with only 1-2 quotes |
| Missing pattern | Return to coding | Add new codes for overlooked areas |
Agent's role:
Transition to Phase 5: "Themes are feeling solid. Shall we finalize the definitions and names together?"
Goal: Finalize themes by articulating their essence and creating evocative names — work through this conversationally with the user.
For Each Theme, Develop Together:
Agent presents template, user contributes:
🔴 This is a TEMPLATE FORMAT only. The theme "Navigating Digital Boundaries" and its definition are EXAMPLES showing the structure. Replace with themes derived from YOUR data.
Let's define Theme 1: "[Theme Name from Your Data]"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DEFINITION:
[Agent proposes based on YOUR data and our conversation]
[Describe the central concept that unites the codes in this theme,
based on patterns found in the actual dataset]
[Ask user] Does this capture the essence? What would you add or change?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SCOPE:
- Includes: [develop together based on your data]
- Excludes: [develop together based on your data]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SUB-THEMES:
1. [Agent suggests based on patterns in YOUR data] [description]
2. [Agent suggests based on patterns in YOUR data] [description]
[Ask user] Do these sub-themes match your understanding? Others?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CONTRIBUTION TO RESEARCH QUESTION:
[develop together]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FINAL NAME OPTIONS:
A. "[Agent's suggestion based on your data]"
B. [User can propose alternatives]
C. "[Alternative evocative name based on your data]"
Which resonates most? Or shall we brainstorm others?
Naming Guidelines*
| Weak Name | Strong Name | Why |
|---|---|---|
| "Problems" | "Navigating systemic neglect" | Captures action + meaning |
| "Feelings" | "Emotional labor of care" | Specific + interpretive |
| "Technology" | "Digital disruption of intimacy" | Evocative + conceptual |
*These show the pattern of weak → strong naming. Do not assume themes about problems, feelings, or technology will be in the data.
Output: Finalized themes with definitions, scope, sub-themes, and evocative names
Transition to Phase 6: "Themes are now finalized. Shall I proceed to produce the final report? I'll generate it autonomously based on what we've developed together."
Goal: Present findings with vivid examples and analytical narrative — proceed autonomously after receiving user permission.
Trigger: User says "yes," "proceed," "generate report," etc.
Report Structure:
Using Quotes Effectively:
Agent delivers:
Coverage Dimensions:
| Dimension | Questions to Ask | Red Flags |
|---|---|---|
| Depth | Are themes richly developed with nuance? | Thin themes with few quotes |
| Breadth | Do themes capture the full dataset? | Important topics missing |
| Balance | Are all participants/themes represented? | Over-reliance on outliers |
| Reflexivity | Has researcher position been examined? | No discussion of bias |
Signs of Avoidance:
Techniques to Surface Avoided Areas:
Negative Case Analysis:
Data Audit:
Reflexive Questions (ask user during conversation):
Gap Analysis Matrix:
| Research Question | Themes Addressing | Gaps Identified |
|---|---|---|
| RQ1: Experience of X | Theme A, Theme B | Missing: negative experiences |
| RQ2: Response to Y | Theme C | Missing: long-term effects |
| # | Criterion | Check |
|---|---|---|
| 1 | Data transcribed to appropriate level | ☐ |
| 2 | Each data item given equal attention | ☐ |
| 3 | Themes not from vivid examples only | ☐ |
| 4 | Themes capture something important about data | ☐ |
| 5 | Data within themes cohere meaningfully | ☐ |
| 6 | Clear distinction between themes | ☐ |
| 7 | Themes internally coherent and distinctive | ☐ |
| 8 | Analysis matches theoretical framework | ☐ |
| 9 | Data extracts relate to identified themes | ☐ |
| 10 | Data extracts sufficient to support claims | ☐ |
| 11 | Analysis makes sense relative to extracts | ☐ |
| 12 | Analysis goes beyond description | ☐ |
| 13 | Analysis is nuanced and sophisticated | ☐ |
| 14 | Analysis tells convincing story about data | ☐ |
| 15 | Analysis addresses research question | ☐ |
| Strategy | Application |
|---|---|
| Prolonged engagement | Spend sufficient time with data |
| Peer debriefing | Regular discussions with user |
| Negative case analysis | Actively seek disconfirming evidence |
| Thick description | Rich, contextualized reporting |
| Audit trail | Document all analytical decisions |
| Reflexivity journal | Track assumptions and positionality |
For collaborative or structured approaches, see references/codebook-guide.md.
THEME: [Name]
├── Code 1: [Name]
│ ├── Definition
│ ├── Inclusion criteria
│ ├── Exclusion criteria
│ └── Examples (2-3)
├── Code 2: [Name]
│ └── ...
When using codebook approaches:
| Pitfall | Solution |
|---|---|
| Theme = Topic Summary | Ensure themes have central organizing concept |
| "Themes emerged" | Use active language: "we identified/developed" |
| Positivism Creep | Maintain methodological coherence |
| Frequency = Significance | Consider meaning, not just frequency |
| Insufficient Familiarization | Read data multiple times before coding |
| Theme Overload | Aim for 4-8 main themes |
| Ignoring Reflexivity | Document researcher position throughout |
| Agent Dominance | Ensure user drives interpretive decisions |
| Use Case | Tool | Notes |
|---|---|---|
| Small projects (<20 interviews) | Spreadsheet + manual coding | Low learning curve |
| Free QDA software | Taguette, QualCoder | Good functionality |
| Commercial QDA | NVivo, MAXQDA, ATLAS.ti | Advanced features |
| Team collaboration | Dedoose | Real-time collaboration |
| AI assistance | Use for suggestions only | Human must lead analysis |
Remember: Thematic analysis is iterative, not linear. Expect to cycle back through phases as your understanding deepens. The conversational workflow ensures user insight guides the interpretive work at the crucial theme development stages.
Automatically, when a task matches. Use when analyzing interview transcripts, survey responses, documents, or any text data to identify codes, develop themes, assess analytical coverage, and determine what areas have been effectively explored versus potentially avoided. Supports both reflexive thematic analysis (Braun & Clarke) and codebook approaches for research rigor. Optimized for chat-based collaborative workflows.
Skills that do similar work, with their headline benchmark lift.
From the same source and nearby in the catalogue.