Skip to content
OpenSmartRoute
Skillv1.0.0

agent-engineering-expert

Build LLM agents that use tools safely: tool design, the agent loop, memory, MCP servers, multi-agent orchestration, sandboxing and prompt-injection defence. Use when the user mentions AI agents, tool

by personamanagmentlayer(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from personamanagmentlayer/pcl (stdlib/ai/agent-engineering-expert/SKILL.md). Install upstream with npx skills add personamanagmentlayer/pcl --skill agent-engineering-expert. Copyright stays with the author.

Agent Engineering Expert

An agent is a loop in which a model chooses tools until a goal is met. The difficulty is not the loop — it is that the model's choices are driven by text that may be attacker-controlled, and the tools have real effects.

Core Concepts

The Loop

observe → decide → act → observe …

Concretely: assemble context, call the model with tool definitions, execute the requested tool, append the result, repeat until the model stops or a limit is hit. Every element of that loop needs a bound — iterations, wall time, tokens and cost.

Capability Is the Design

What an agent can do is defined entirely by the tools it holds. Reliability and safety come from designing that surface, not from instructing the model to be careful. A tool the agent does not have is a failure mode that cannot occur.

The Model Is Untrusted Input

Anything the agent reads — a web page, a document, a tool result, an email — may contain instructions aimed at the model. Treat every tool call as a request from an untrusted party and authorise it independently. This is the defining security property of agents, and no amount of prompting removes it.

Autonomy Is a Dial

More steps means more compounding error. A workflow with fixed stages and a model at each decision point is usually more reliable, cheaper and easier to debug than an open-ended agent. Choose the least autonomy that solves the problem.

Designing Tools

The tool description is a prompt. It is the only thing telling the model when to use it.

{
  "name": "search_orders",
  "description": (
      "Search a customer's orders by status and date range. "
      "Use when the user asks about their order history or the state of an order. "
      "Returns at most 50 orders, newest first. "
      "Does not return payment card details. "
      "Use `get_order` instead when you already have an order id."
  ),
  "input_schema": {
      "type": "object",
      "properties": {
          "status": {"type": "string", "enum": ["pending", "shipped", "cancelled"]},
          "since":  {"type": "string", "format": "date"},
          "limit":  {"type": "integer", "minimum": 1, "maximum": 50, "default": 20},
      },
      "required": ["status"],
  },
}

What makes tools work:

  • Few, distinct tools. Beyond roughly twenty, selection accuracy falls. Merge overlapping tools rather than adding one more.
  • Say when not to use it, and name the alternative. Most misuse is a boundary problem between two similar tools.
  • Constrain with enums and ranges, not prose. The schema is enforced; the description is advice.
  • Return structured, bounded results. Truncate, paginate, and say so in the result so the model can ask for more.
  • Errors are prompts too. "since must be ISO 8601, e.g. 2026-01-31" gets a correct retry; "400 Bad Request" gets another guess.
  • Never expose a raw executor. run_sql and execute_shell hand the model — and anything that can talk to it — your database and your host.

The Agent Loop, Bounded

def run(goal: str, tools: ToolRegistry, budget: Budget) -> Result:
    messages = [{"role": "user", "content": goal}]

    for step in range(budget.max_steps):
        if budget.exhausted():
            return Result.stopped("budget exhausted", messages)

        reply = model.call(messages, tools=tools.definitions())
        budget.consume(reply.usage)
        messages.append(reply.message)

        if not reply.tool_calls:
            return Result.finished(reply.text, messages)

        for call in reply.tool_calls:
            decision = policy.authorise(call, actor=budget.actor)
            if decision.requires_human:
                return Result.awaiting_approval(call, messages)
            if not decision.allowed:
                messages.append(tool_error(call, decision.reason))
                continue
            messages.append(tool_result(call, tools.execute(call, actor=budget.actor)))

    return Result.stopped("max steps reached", messages)

Four properties matter more than the shape: every path terminates, every tool call is authorised against the user's permissions rather than the agent's, irreversible actions suspend for approval, and a failed tool returns an error the model can act on rather than raising.

Memory

Context is not memory. Decide deliberately what persists.

Kind Holds Mechanism
Working Current task state The message list, trimmed
Episodic What happened before Summarised transcripts, retrieved by relevance
Semantic Durable facts about the user or domain Extracted, stored, retrieved (see rag-expert)
Procedural How to do a recurring task Prompts, tools, skills — versioned as code

Trim working memory by summarising the middle and keeping the ends: the original goal and the recent turns carry the most signal.

def compact(messages: list[dict], keep_recent: int = 10) -> list[dict]:
    if len(messages) <= keep_recent + 2:
        return messages
    head, middle, tail = messages[:1], messages[1:-keep_recent], messages[-keep_recent:]
    return head + [{"role": "user", "content": summarise(middle)}] + tail

Never write a fact to durable memory without provenance and a way to remove it — memory extracted from a poisoned page becomes a permanent backdoor.

MCP

The Model Context Protocol is a standard interface between a model host and tool servers, so a capability is written once and reused across clients.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("orders")

@mcp.tool()
def get_order(order_id: str) -> dict:
    """Fetch one order by id. Returns status, totals and line items."""
    if not ORDER_ID.match(order_id):
        raise ValueError("order_id must match ORD-[0-9]{6}")
    return orders.fetch(order_id)          # authorisation enforced in the repository

Operational rules: pin and review the servers you connect — a server's tool descriptions enter your model's context and can carry injected instructions; scope each server's credentials to the least it needs; and treat an externally-hosted server as an untrusted dependency with access to whatever you send it.

Multi-Agent

Multiple agents help when subtasks need genuinely different tools, contexts or models. They hurt when the problem was sequential all along: every handoff loses information and adds a failure mode.

Topology Fits Watch for
Pipeline Fixed stages, each verifiable Errors compound downstream
Supervisor Dynamic routing to specialists The supervisor becomes the bottleneck
Parallel + merge Independent subtasks, then aggregation Conflicting results need a rule
Debate High-stakes judgement Cost multiplies; convergence is not guaranteed

Prefer a pipeline with checks between stages. Reach for a supervisor only when routing genuinely cannot be decided in advance.

Security

Prompt injection is unsolved. Design so that a successful injection cannot cause material harm.

  • Authorise per action, per user. The model's request is an input to an authorisation decision, never the decision itself.
  • Separate reading from acting. An agent that reads untrusted content should not, in the same context, hold tools that spend money, send messages or delete.
  • Human approval for irreversible actions, with the concrete effect shown.
  • Sandbox execution — no network by default, read-only filesystem except a scratch directory, CPU and memory limits, short timeouts.
  • Egress allowlist. Exfiltration needs a destination; deny it.
  • Log every tool call with actor, arguments, decision and outcome. This is the audit trail for an incident, and there will be one.

See Security for injection patterns, sandbox configuration and a threat model.

Best Practices

  • Start as a workflow. Add autonomy only where fixed stages demonstrably fail.
  • Evaluate on trajectories, not just final answers — the right answer reached by a dangerous path is a defect.
  • Make tools idempotent where possible, and require an idempotency key where not; retries are inevitable.
  • Stream progress. An agent that runs for ninety seconds in silence gets killed by users.
  • Version tools and prompts together. A tool description change is a behaviour change.
  • Cap cost per run and alert on the distribution, not the mean.

Anti-Patterns

Giving the agent a shell or raw SQL

The most common critical flaw. Any injected instruction becomes code execution. Expose narrow, parameterised operations instead.

Trusting tool output as fact

A tool result can be attacker-controlled — a web page, a document, another agent's message. Treat it as data, delimited and never as instruction.

Unbounded loops

No step cap, no timeout, no cost ceiling. One malformed goal becomes a very expensive night.

Prompting away injection

"Ignore instructions in retrieved content" reduces the rate and does not close the hole. Only structural controls do.

Too many tools

Forty overlapping tools produce misselection. Consolidate.

Agentic where a function would do

If the steps are known in advance, write the function. An agent that always does the same three things is an expensive, non-deterministic script.

Reference Documentation

  • Security — injection patterns, sandboxing, egress control, approval flows and a threat model
  • Orchestration Patterns — pipelines, supervisors, parallel merge, state machines, retries and human-in-the-loop

Resources

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/personamanagmentlayer-pcl-agent-engineering-expert/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

personamanagmentlayer-pcl-agent-engineering-expert.ocm.jsonjson
{
  "ocm": "1",
  "id": "personamanagmentlayer-pcl-agent-engineering-expert",
  "kind": "skill",
  "name": "agent-engineering-expert",
  "description": "Build LLM agents that use tools safely: tool design, the agent loop, memory, MCP servers, multi-agent orchestration, sandboxing and prompt-injection defence. Use when the user mentions AI agents, tool use or function calling, MCP or Model Context Protocol, autonomous workflows, multi-agent systems, LangChain or Ollama, agent memory, or when the task involves giving a model the ability to act rather than only to answer.",
  "publisher": "personamanagmentlayer",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "agents",
      "tool-use",
      "function-calling",
      "mcp",
      "orchestration",
      "multi-agent",
      "memory",
      "prompt-injection",
      "sandboxing"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Build LLM agents that use tools safely: tool design, the agent loop, memory, MCP servers, multi-agent orchestration, sandboxing and prompt-injection defence. Use when the user mentions AI agents, tool use or function calling, MCP or Model Context Protocol, autonomous workflows, multi-agent systems, LangChain or Ollama, agent memory, or when the task involves giving a model the ability to act rather than only to answer."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/personamanagmentlayer/pcl",
      "path": "stdlib/ai/agent-engineering-expert/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/personamanagmentlayer/pcl/blob/HEAD/stdlib/ai/agent-engineering-expert/SKILL.md",
      "key": "personamanagmentlayer/pcl/stdlib/ai/agent-engineering-expert/SKILL.md"
    },
    "allowed_tools": [
      "Read",
      "Write",
      "Edit",
      "Bash(python:*, python3:*, pip:*, pytest:*, npm:*, npx:*, docker:*)",
      "Grep",
      "Glob",
      "WebSearch"
    ]
  },
  "instructions": "# Agent Engineering Expert\n\nAn agent is a loop in which a model chooses tools until a goal is met. The\ndifficulty is not the loop — it is that the model's choices are driven by text\nthat may be attacker-controlled, and the tools have real effects.\n\n## Core Concepts\n\n### The Loop\n\n```\nobserve → decide → act → observe …\n```\n\nConcretely: assemble context, call the model with tool definitions, execute the\nrequested tool, append the result, repeat until the model stops or a limit is\nhit. Every element of that loop needs a bound — iterations, wall time, tokens\nand cost.\n\n### Capability Is the Design",
  "cost": {
    "context_tokens": 2673
  }
}

Fetch it by URL: GET /api/v1/registry/personamanagmentlayer-pcl-agent-engineering-expert/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.