mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

Dev Tools

Scientific Agent Skills: How 177 Validated Tools Turn Any Agent Into a Lab Scientist

Examine the plumbing behind a production-grade agent skills library: validation patterns, database integration boundaries, and cross-agent compatibility.

Source: github.com
Scientific Agent Skills: How 177 Validated Tools Turn Any Agent Into a Lab Scientist

Most agent tool libraries ship JSON schemas and hope for the best. Scientific Agent Skills ships 177 validated functions that query 100+ scientific databases without exposing credentials, breaking rate limits, or leaving agents stranded when PubChem returns a 429.

The library hit 51,483 GitHub stars and claims 250,000+ scientists as users. That scale forces real answers to plumbing questions most agent projects ignore: how do you validate tools across Cursor, Claude Code, and Codex without duplicating test infrastructure? How do you let an agent chain sequence retrieval, alignment, and visualization without leaking API keys in tool definitions? How do you handle partial results when GenBank times out halfway through a batch query?

What It Actually Does

Scientific Agent Skills is a Python package that exposes domain-specific functions as agent tools. Each skill wraps an API call to a scientific database (UniProt, PubChem, GenBank, ChEMBL) or computation service. The library handles authentication, rate limiting, error recovery, and response normalization so agents see clean JSON instead of raw HTTP chaos.

The skills cover:

  • Biology: genomics, proteomics, metabolomics, sequence alignment
  • Chemistry: molecular structure search, property prediction, reaction databases
  • Medicine: clinical trial lookups, drug interaction checks, disease ontology queries
  • Materials science: crystal structure databases, property calculators

Each skill includes a JSON schema that describes parameters, return types, and failure modes. The library supports both the Agent Skills standard (a community spec for tool definitions) and the Agent Plugins standard (a competing spec with slightly different metadata requirements).

Validation Across Agent Runtimes

The repository includes GitHub Actions workflows for security scanning and skill testing. The skill test workflow runs every skill against a matrix of agent runtimes: Cursor, Claude Code, Codex, and a few others.

Here’s the validation pattern:

# Simplified from the actual test harness
class SkillValidator:
    def __init__(self, runtime: str):
        self.runtime = runtime
        self.client = self._get_runtime_client(runtime)
    
    def validate_skill(self, skill_def: dict) -> ValidationResult:
        # 1. Schema validation
        schema_valid = self._validate_schema(skill_def)
        
        # 2. Runtime compatibility check
        runtime_valid = self._check_runtime_compat(skill_def)
        
        # 3. Live execution test with mock data
        exec_result = self._execute_with_mock(skill_def)
        
        # 4. Error handling verification
        error_result = self._test_error_paths(skill_def)
        
        return ValidationResult(
            schema=schema_valid,
            runtime=runtime_valid,
            execution=exec_result,
            errors=error_result
        )

The test harness doesn’t duplicate infrastructure. Instead, it uses a plugin architecture where each runtime implements a common interface. The validator calls execute_tool(skill_name, params) and checks that the response matches the schema, regardless of whether Cursor or Claude Code is running the tool.

This works because the library separates skill definitions (pure data) from skill implementations (Python functions). The definition is a JSON file that any agent can parse. The implementation is a Python module that the library loads at runtime.

Authentication and Rate Limiting Boundaries

Agents should never see raw API keys. Scientific Agent Skills uses a credential manager that stores keys in environment variables or a local secrets file. When an agent calls a skill, the library injects credentials at execution time.

Here’s the flow:

  1. Agent sends tool call: {"skill": "pubchem_search", "params": {"query": "aspirin"}}
  2. Library looks up pubchem_search implementation
  3. Implementation requests credentials from credential manager
  4. Credential manager returns API key (or errors if missing)
  5. Implementation makes HTTP request with key in header
  6. Response is sanitized (no keys in logs or return values)
  7. Agent receives clean JSON

Rate limiting happens at the same boundary. Each database has different limits (PubChem allows 5 requests/second, UniProt allows 10/second). The library maintains a token bucket for each database and blocks tool execution if the bucket is empty.

class RateLimiter:
    def __init__(self, database: str, rate: int, period: int):
        self.database = database
        self.rate = rate
        self.period = period
        self.tokens = rate
        self.last_refill = time.time()
    
    def acquire(self) -> bool:
        self._refill()
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False
    
    def _refill(self):
        now = time.time()
        elapsed = now - self.last_refill
        new_tokens = elapsed * (self.rate / self.period)
        self.tokens = min(self.rate, self.tokens + new_tokens)
        self.last_refill = now

If an agent tries to call a skill and the rate limiter blocks it, the library returns an error with a retry-after timestamp. The agent can choose to wait or move on to a different task.

Interop Between Agent Skills and Agent Plugins

The Agent Skills standard and Agent Plugins standard both define how to describe tools, but they use different metadata formats. Agent Skills uses a flat JSON structure with name, description, parameters, and returns. Agent Plugins uses a nested structure with metadata, input_schema, and output_schema.

Scientific Agent Skills supports both by maintaining two parallel definition files for each skill. The Python implementation is identical; only the metadata wrapper changes.

AspectAgent SkillsAgent Plugins
Schema formatFlat JSONNested JSON
Parameter typesJSON Schema draft-07OpenAPI 3.0
Error handlingerror field in responseHTTP status codes
VersioningSemantic versioning in filenameVersion field in metadata
DiscoveryDirectory scanPlugin registry API

The library includes a converter that generates Agent Plugins definitions from Agent Skills definitions. This keeps maintenance burden low: you write one skill, run the converter, and get both formats.

Failure Modes in Tool Chains

Agents often chain scientific tools: retrieve a protein sequence from UniProt, align it against a reference database, visualize the alignment. Each step can fail in different ways.

Common failure modes:

  • Timeout: GenBank takes 30 seconds to return a large sequence, agent times out at 20 seconds
  • Partial results: PubChem returns 50 compounds but the query matched 200
  • Dependency failure: Alignment tool requires a sequence in FASTA format, but retrieval tool returned JSON
  • Rate limit: Agent hits UniProt 15 times in one second, gets blocked for 60 seconds
  • Invalid input: Agent passes a malformed SMILES string to a chemistry tool

The library handles these with a combination of retries, partial result flags, and explicit error types.

For timeouts, each skill has a configurable timeout (default 30 seconds). If the underlying API doesn’t respond in time, the skill returns an error with type: "timeout" and retry_after: null (meaning don’t retry, the query is too expensive).

For partial results, skills that query large datasets include a truncated: true flag in the response and a next_page_token if pagination is available. Agents can choose to request the next page or work with what they have.

For dependency failures, the library includes a type system that validates inputs before execution. If a skill expects FASTA and receives JSON, it errors immediately with a clear message instead of passing garbage to the API.

For rate limits, the library returns type: "rate_limit" with retry_after: 60 (seconds). Agents can schedule a retry or switch to a different database.

For invalid input, the library validates parameters against the JSON schema before making any API calls. This catches most errors early and avoids wasting API quota on bad requests.

Deployment Shape

Scientific Agent Skills is a Python package installed via pip. It has no server component. Agents import the library and call skills as Python functions. This keeps deployment simple but limits cross-language support (you can’t call these skills from a JavaScript agent without wrapping them in an HTTP server).

The library depends on:

  • requests for HTTP calls
  • pydantic for schema validation
  • tenacity for retry logic
  • cryptography for credential encryption

It stores credentials in ~/.scientific-agent-skills/secrets.json (encrypted with a key derived from the user’s environment). Rate limiter state lives in memory and resets on restart.

For production use, you’d want to:

  • Move credentials to a secrets manager (AWS Secrets Manager, HashiCorp Vault)
  • Persist rate limiter state to Redis or a database
  • Add observability (structured logging, OpenTelemetry traces)
  • Wrap the library in an HTTP server if you need cross-language support

Observability Gaps

The library logs errors but doesn’t expose metrics or traces. You can’t answer questions like:

  • Which skills are called most often?
  • What’s the p95 latency for PubChem queries?
  • How many tool calls fail due to rate limits vs. timeouts?
  • Which agent runtime has the highest error rate?

Adding observability would require:

  1. Instrumenting each skill with OpenTelemetry spans
  2. Emitting metrics (call count, latency, error rate) to Prometheus or StatsD
  3. Logging structured events (JSON lines with skill name, parameters, result, duration)
  4. Correlating tool calls with agent sessions (requires passing a trace context through the agent runtime)

Without this, debugging production issues is hard. You know a skill failed, but you don’t know if it’s a one-off or a systemic problem.

Technical Verdict

Use Scientific Agent Skills when:

  • You’re building agents that need to query scientific databases (genomics, chemistry, medicine)
  • You want validated, production-tested tools instead of writing API wrappers yourself
  • You need cross-agent compatibility (Cursor, Claude Code, Codex)
  • You’re okay with Python-only deployment

Avoid it when:

  • You need cross-language support (JavaScript, Go, Rust agents)
  • You require real-time observability (metrics, traces, dashboards)
  • You need custom authentication flows (OAuth, SAML, federated identity)
  • You want to run skills in a sandboxed environment (the library executes arbitrary Python)

The library solves real plumbing problems (credential management, rate limiting, schema validation) but leaves observability and deployment flexibility on the table. For scientific computing agents, it’s a solid foundation. For production multi-tenant systems, you’ll need to wrap it in additional infrastructure.