claude-api — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited claude-api (Agent Skill) and scored it 91/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.
ignore/disregard/forget … previous instructions sentence.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Scan the project for package.json, requirements.txt, pyproject.toml, build.gradle, or go.mod to identify the language.
# Python
pip install anthropic
# Node.js / TypeScript
npm install @anthropic-ai/sdk
# Go
go get github.com/anthropics/anthropic-sdk-go| Model | Best For | Speed | Cost |
|---|---|---|---|
claude-opus-4-5 | Complex reasoning, coding, research | Slower | Higher |
claude-sonnet-4-5 | Balanced - most tasks | Medium | Medium |
claude-haiku-3-5 | Fast, lightweight tasks, classification | Fast | Lower |
Default to `claude-opus-4-5` for new implementations unless the user specifies otherwise or speed/cost is a constraint.
import anthropic
import os
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
message = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Explain the CAP theorem in simple terms."}
]
)
print(message.content[0].text)import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic() // reads ANTHROPIC_API_KEY from env
const message = await client.messages.create({
model: 'claude-opus-4-5',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Explain the CAP theorem in simple terms.' }
],
})
console.log(message.content[0].text)conversation_history = []
def chat(user_message: str) -> str:
conversation_history.append({"role": "user", "content": user_message})
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=2048,
system="You are a senior software engineer. Be concise and precise.",
messages=conversation_history
)
assistant_message = response.content[0].text
conversation_history.append({"role": "assistant", "content": assistant_message})
return assistant_messageUse streaming for long outputs to reduce perceived latency:
# Python - streaming
with client.messages.stream(
model="claude-opus-4-5",
max_tokens=4096,
messages=[{"role": "user", "content": "Write a detailed explanation of neural networks"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)// TypeScript - streaming
const stream = client.messages.stream({
model: 'claude-opus-4-5',
max_tokens: 4096,
messages: [{ role: 'user', content: 'Write a detailed explanation of neural networks' }],
})
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' && chunk.delta.type === 'text_delta') {
process.stdout.write(chunk.delta.text)
}
}tools = [
{
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name, e.g. 'London'"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
}
]
def get_weather(location: str, unit: str = "celsius") -> dict:
# Your actual implementation
return {"temperature": 15, "condition": "cloudy", "location": location}
# Agentic loop
messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
while True:
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
tools=tools,
messages=messages
)
messages.append({"role": "assistant", "content": response.content})
if response.stop_reason == "end_turn":
# Final text response - done
for block in response.content:
if hasattr(block, "text"):
print(block.text)
break
# Process tool calls
tool_results = []
for block in response.content:
if block.type == "tool_use":
if block.name == "get_weather":
result = get_weather(**block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result),
})
messages.append({"role": "user", "content": tool_results})import base64
# From URL
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "url", "url": "https://example.com/chart.png"},
},
{"type": "text", "text": "What does this chart show?"},
],
}]
)
# From file (base64)
with open("diagram.png", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "image",
"source": {"type": "base64", "media_type": "image/png", "data": image_data},
},
{"type": "text", "text": "Describe this diagram."},
],
}]
)Cache large system prompts or repeated context to reduce costs by up to 90%:
# Mark cacheable content with cache_control
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are an expert in our codebase. " + very_long_codebase_context,
"cache_control": {"type": "ephemeral"} # cache this block
}
],
messages=[{"role": "user", "content": user_question}]
)
# Check cache usage in response
print(response.usage.cache_creation_input_tokens) # tokens written to cache
print(response.usage.cache_read_input_tokens) # tokens read from cacheCaching rules:
cache_controlFor complex reasoning tasks (math, coding, analysis):
response = client.messages.create(
model="claude-opus-4-5",
max_tokens=16000,
thinking={
"type": "enabled",
"budget_tokens": 10000 # allow up to 10k tokens of internal thinking
},
messages=[{"role": "user", "content": "Prove that there are infinitely many primes."}]
)
for block in response.content:
if block.type == "thinking":
print("Thinking:", block.thinking[:200], "...") # internal reasoning
elif block.type == "text":
print("Answer:", block.text)For large-scale offline processing (50% cost reduction):
# Create batch
batch = client.messages.batches.create(requests=[
{
"custom_id": f"task-{i}",
"params": {
"model": "claude-haiku-3-5",
"max_tokens": 512,
"messages": [{"role": "user", "content": text}]
}
}
for i, text in enumerate(texts)
])
# Poll until complete
import time
while True:
batch = client.messages.batches.retrieve(batch.id)
if batch.processing_status == "ended":
break
time.sleep(60)
# Retrieve results
for result in client.messages.batches.results(batch.id):
print(result.custom_id, result.result.message.content[0].text)| Tier | Pattern | When to Use |
|---|---|---|
| 1 | Single API call | Classification, extraction, summarization |
| 2 | Multi-turn + tools | Research assistant, coding helper |
| 3 | Managed Agents | Long-running autonomous tasks |
ANTHROPIC_API_KEY environment variableresponse.stop_reason; "tool_use" means loop continuescache_control to large system prompts to cut costs~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.