<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: tercel</title>
    <description>The latest articles on DEV Community by tercel (@tercelyi).</description>
    <link>https://dev.to/tercelyi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3781875%2Fd782a4aa-43be-460e-bea4-e6afcf0a2607.png</url>
      <title>DEV Community: tercel</title>
      <link>https://dev.to/tercelyi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tercelyi"/>
    <language>en</language>
    <item>
      <title>Give Your Coding Agent a Governed CLI Workflow with apexe</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Fri, 16 Oct 2026 12:14:58 +0000</pubDate>
      <link>https://dev.to/tercelyi/give-your-coding-agent-a-governed-cli-workflow-with-apexe-500j</link>
      <guid>https://dev.to/tercelyi/give-your-coding-agent-a-governed-cli-workflow-with-apexe-500j</guid>
      <description>&lt;p&gt;An agent task starts simply: list a directory, read a file, inspect a tool. As the task grows, those small calls become a workflow with real permissions and side effects.&lt;/p&gt;

&lt;p&gt;That is a useful place to introduce &lt;strong&gt;apexe&lt;/strong&gt;: a governed execution layer for CLI tools and HTTP APIs. It gives existing commands typed contracts and applies configured policy before execution, with records of executions and refusals.&lt;/p&gt;

&lt;p&gt;Here is how to start with a local CLI workflow, then connect it to the agent or protocol client you use.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prepare apexe and a trusted CLI
&lt;/h2&gt;

&lt;p&gt;Use a &lt;a href="https://github.com/aiperceivable/apexe/releases" rel="noopener noreferrer"&gt;prebuilt binary&lt;/a&gt;, or build from source with stable Rust and Cargo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aiperceivable/apexe.git
&lt;span class="nb"&gt;cd &lt;/span&gt;apexe
cargo &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
apexe &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow below targets Unix CLI tools. macOS and Linux are the main starting points; native Windows CLI discovery is not supported. Git is needed to acquire the rules corpus, and the CLI binaries you want to use must already be installed.&lt;/p&gt;

&lt;p&gt;Initialize coverage and inspect the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe init
apexe list &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;init&lt;/code&gt; obtains the configured rules source, normally &lt;a href="https://github.com/aiperceivable/cli-permissions" rel="noopener noreferrer"&gt;cli-permissions&lt;/a&gt;, checks matching installed commands and variants, and writes bindings plus a starter ACL.&lt;/p&gt;

&lt;p&gt;Review &lt;code&gt;~/.apexe/acl.yaml&lt;/code&gt;. A new policy defaults to deny, with generated allow rules for local readonly operations. Existing manual rules and policy defaults are preserved. Treat generated classifications as material to review.&lt;/p&gt;

&lt;p&gt;Read the init report, including skipped tools, warnings, and &lt;code&gt;native_ready&lt;/code&gt; module IDs. This is where you learn which entry points your installation can actually use.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Preview one native invocation
&lt;/h2&gt;

&lt;p&gt;Native execution accepts familiar argv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this example, you need a matching reviewed native binding. The current native pilot covers &lt;strong&gt;BSD &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, and &lt;code&gt;ls&lt;/code&gt;&lt;/strong&gt;. A Linux installation may successfully scan GNU tools while lacking native grammar for this call; scanning coverage and native eligibility are separate.&lt;/p&gt;

&lt;p&gt;Inspect the preflight's validity, execution mode, module, ACL decision, approval requirement, and argument/path checks. Confirm that it describes the operation and policy you intended.&lt;/p&gt;

&lt;p&gt;Only after reading an admitted preflight, submit a separate execution call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Native stdout and stderr pass through, and apexe preserves the child's exit status. You do not need to activate a shell environment or run an MCP server.&lt;/p&gt;

&lt;p&gt;Keep preview and execution separate in an agent workflow: the point is to inspect the result before starting the child. Execution checks the request again; a preview does not reserve permission or grant human approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Use module JSON when the binding has no native grammar
&lt;/h2&gt;

&lt;p&gt;Module JSON is another local interface. Start by inspecting the installed schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe list &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output's &lt;code&gt;modules&lt;/code&gt; array contains each module's &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;input_schema&lt;/code&gt;. Use the property names and shapes from your own binding.&lt;/p&gt;

&lt;p&gt;For example, &lt;strong&gt;if&lt;/strong&gt; your &lt;code&gt;cli.ls&lt;/code&gt; schema advertises a &lt;code&gt;file&lt;/code&gt; array, preview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe &lt;span class="nb"&gt;exec &lt;/span&gt;cli.ls &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s1"&gt;'{"file":["."]}'&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After inspecting an admitted result, execute separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe &lt;span class="nb"&gt;exec &lt;/span&gt;cli.ls &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s1"&gt;'{"file":["."]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Module mode captures the result as JSON, including &lt;code&gt;stdout&lt;/code&gt;, &lt;code&gt;stderr&lt;/code&gt;, and &lt;code&gt;exit_code&lt;/code&gt;; it supplies null child stdin. Native mode preserves streams, with stdin inheritance only where reviewed capabilities permit it.&lt;/p&gt;

&lt;p&gt;Both routes apply their normal governance checks. A missing native grammar can justify selecting module JSON for the same operation. An ACL or path refusal calls for resolving the denied request with the operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Give your terminal agent the same workflow
&lt;/h2&gt;

&lt;p&gt;apexe includes one shared routing Skill for &lt;strong&gt;Claude Code, Codex, pi, and OpenCode&lt;/strong&gt;. From the source checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 scripts/install_agent_skill.py &lt;span class="nt"&gt;--project-dir&lt;/span&gt; /path/to/your-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace that destination with the project where the agent works. Follow the &lt;a href="https://github.com/aiperceivable/apexe/blob/main/docs/agent-skill.md" rel="noopener noreferrer"&gt;Agent Skill guide&lt;/a&gt; to declare the execution route and selected policy in the host's project instructions.&lt;/p&gt;

&lt;p&gt;The Skill guides the agent to resolve configuration before its first task command, route external CLI calls through explicit &lt;code&gt;exec&lt;/code&gt;, preview new or changed calls, and stop on governance refusals. Explicit exec works without shims or MCP.&lt;/p&gt;

&lt;p&gt;For a pipeline, the shell still owns the pipe. Each external stage needs its own governed invocation, and the Skill calls for preflighting stages sequentially before execution. Shell redirection happens outside apexe's typed-path checks.&lt;/p&gt;

&lt;p&gt;Installing the Skill alone does not enroll every project or intercept an unrestricted terminal. Compulsory routing requires host enforcement.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Add an interface when you need it
&lt;/h2&gt;

&lt;p&gt;For existing shell workflows, optional &lt;code&gt;env&lt;/code&gt; integration installs eligible external-command shims:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="nt"&gt;--enable&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.apexe/bin/apexe-activate.sh
apexe &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="nt"&gt;--check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this after bindings and policy are ready. Shims preserve familiar command names for covered tools. Builtins, aliases, absolute paths, and uncovered commands remain outside that route.&lt;/p&gt;

&lt;p&gt;For an MCP client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe serve &lt;span class="nt"&gt;--acl&lt;/span&gt; ~/.apexe/acl.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For A2A:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe a2a &lt;span class="nt"&gt;--acl&lt;/span&gt; ~/.apexe/acl.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Servers need the explicit ACL flag for access control. Local exec uses caller &lt;code&gt;local&lt;/code&gt; and loads the default ACL when present; if none is loaded, access control is inactive. MCP interactive approval is opt-in with &lt;code&gt;--enable-approval&lt;/code&gt; and a compatible client. Local execution has no interactive approval client, so calls that actually need that decision fail closed. A2A has no interactive approval transport; approval-store support requires library integration.&lt;/p&gt;

&lt;p&gt;Have an HTTP API too? &lt;code&gt;serve&lt;/code&gt; and &lt;code&gt;a2a&lt;/code&gt; can import supported operations from OpenAPI 3.0/3.1 documents alongside CLI modules. See the &lt;a href="https://github.com/aiperceivable/apexe/blob/main/docs/openapi.md" rel="noopener noreferrer"&gt;OpenAPI guide&lt;/a&gt; for the supported JSON proxy surface and credential setup. HTTP import is a server feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the contract current
&lt;/h2&gt;

&lt;p&gt;After a CLI changes, check its source contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apexe verify &lt;span class="nt"&gt;--report&lt;/span&gt; ./drift-report.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional explicit behavioral cases add evidence for the invocations tested. Recorded evidence is bound to binding, executable, and case digests, so changes can invalidate it. It does not certify every possible use of a CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know the execution boundary
&lt;/h2&gt;

&lt;p&gt;Governed CLI calls use structured inputs, configured ACLs, schema-typed path checks, environment scrubbing, timeouts, and auditing. apexe passes argv to the subprocess without evaluating a shell command string.&lt;/p&gt;

&lt;p&gt;An allowed process still has the host process's privileges. &lt;strong&gt;apexe is not an OS sandbox.&lt;/strong&gt; Pair it with the account and isolation boundary your workload needs, and read the &lt;a href="https://github.com/aiperceivable/apexe/blob/main/docs/threat-model.md" rel="noopener noreferrer"&gt;threat model&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project is Rust-based and Apache-2.0 licensed. Start with one trusted CLI and one operation you can inspect from preflight through audit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aiperceivable/apexe" rel="noopener noreferrer"&gt;Explore apexe on GitHub&lt;/a&gt; · &lt;a href="https://github.com/aiperceivable/apexe/blob/main/docs/quickstart.md" rel="noopener noreferrer"&gt;Read the quick start&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which CLI would you like your agent to use through a reviewed execution contract?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>cli</category>
      <category>mcp</category>
      <category>openapi</category>
    </item>
    <item>
      <title>Distributed Orchestration vs Agent Reasoning</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Thu, 15 Oct 2026 02:47:51 +0000</pubDate>
      <link>https://dev.to/tercelyi/distributed-orchestration-vs-agent-reasoning-lj6</link>
      <guid>https://dev.to/tercelyi/distributed-orchestration-vs-agent-reasoning-lj6</guid>
      <description>&lt;p&gt;A lot of “AI agent orchestration” diagrams quietly merge two very different responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deciding what to do next (reasoning)&lt;/li&gt;
&lt;li&gt;actually running distributed work reliably (orchestration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever operated a workflow engine, you know the second problem doesn’t go away just because a model is choosing the steps.&lt;/p&gt;

&lt;p&gt;Agents are planners, not workflow engines&lt;/p&gt;

&lt;p&gt;Agent frameworks are great at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaking down fuzzy tasks&lt;/li&gt;
&lt;li&gt;picking tools / capabilities&lt;/li&gt;
&lt;li&gt;adapting a plan based on intermediate outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They’re not good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;guaranteeing retries and idempotency&lt;/li&gt;
&lt;li&gt;managing long‑running state&lt;/li&gt;
&lt;li&gt;coordinating fan‑out and aggregation at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are classic workflow concerns.&lt;/p&gt;

&lt;p&gt;What orchestration is responsible for&lt;/p&gt;

&lt;p&gt;A real orchestration layer needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;persist workflow state&lt;/li&gt;
&lt;li&gt;handle node restarts and deploys without losing work&lt;/li&gt;
&lt;li&gt;retry failed steps with backoff&lt;/li&gt;
&lt;li&gt;apply idempotency / deduplication&lt;/li&gt;
&lt;li&gt;support compensation / rollbacks for multi‑step flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an agentic system, that orchestration is often built on top of a governed capability runtime.&lt;/p&gt;

&lt;p&gt;Why pair a runtime with orchestration?&lt;/p&gt;

&lt;p&gt;A protocol‑neutral capability runtime gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schema‑validated inputs/outputs for each operation&lt;/li&gt;
&lt;li&gt;identity / ACL / approval checks&lt;/li&gt;
&lt;li&gt;structured traces and events per invocation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An orchestrator then uses those capabilities as building blocks, chaining them together under strong guarantees.&lt;/p&gt;

&lt;p&gt;The agent stays in the role of planner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it proposes which capabilities to call and with which parameters&lt;/li&gt;
&lt;li&gt;it can react to structured errors and adjust the plan&lt;/li&gt;
&lt;li&gt;it doesn’t try to be the persistence or retry layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation has practical benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debuggability&lt;br&gt;
When a flow fails, you can see where: in planning, in runtime validation, or in orchestrated execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safety&lt;br&gt;
Every step is subject to the same ACLs, approvals, and audit behavior, regardless of whether it was triggered by an agent or a human.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evolution&lt;br&gt;
You can swap agent frameworks or tool protocols without rewriting the orchestration and governance layers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A small, realistic first step&lt;/p&gt;

&lt;p&gt;If you’re starting from an agent demo that calls services directly, you don’t have to refactor everything at once.&lt;/p&gt;

&lt;p&gt;Try this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pick a single, non‑trivial flow (e.g., canary deploy, batch data fix)&lt;/li&gt;
&lt;li&gt;expose the underlying operations as governed capabilities with schemas&lt;/li&gt;
&lt;li&gt;route all calls through a runtime that adds identity, ACLs, approvals, and traces&lt;/li&gt;
&lt;li&gt;have a simple orchestrator (queue + worker, or a workflow engine you already use) own retries and long‑running state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that path works, expand the set of capabilities and flows that use it.&lt;/p&gt;

&lt;p&gt;The key shift is mental: treat agents as planners on top of a governed, orchestrated system – not as replacements for the parts of your stack that already give you reliability guarantees.&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Distributed Orchestration vs Agent Reasoning</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Wed, 14 Oct 2026 02:38:17 +0000</pubDate>
      <link>https://dev.to/tercelyi/distributed-orchestration-vs-agent-reasoning-2efm</link>
      <guid>https://dev.to/tercelyi/distributed-orchestration-vs-agent-reasoning-2efm</guid>
      <description>&lt;p&gt;A lot of “AI agent orchestration” diagrams quietly merge two very different responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deciding what to do next (reasoning)&lt;/li&gt;
&lt;li&gt;actually running distributed work reliably (orchestration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever operated a workflow engine, you know the second problem doesn’t go away just because a model is choosing the steps.&lt;/p&gt;

&lt;p&gt;Agents are planners, not workflow engines&lt;/p&gt;

&lt;p&gt;Agent frameworks are great at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaking down fuzzy tasks&lt;/li&gt;
&lt;li&gt;picking tools / capabilities&lt;/li&gt;
&lt;li&gt;adapting a plan based on intermediate outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They’re not good at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;guaranteeing retries and idempotency&lt;/li&gt;
&lt;li&gt;managing long‑running state&lt;/li&gt;
&lt;li&gt;coordinating fan‑out and aggregation at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are classic workflow concerns.&lt;/p&gt;

&lt;p&gt;What orchestration is responsible for&lt;/p&gt;

&lt;p&gt;A real orchestration layer needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;persist workflow state&lt;/li&gt;
&lt;li&gt;handle node restarts and deploys without losing work&lt;/li&gt;
&lt;li&gt;retry failed steps with backoff&lt;/li&gt;
&lt;li&gt;apply idempotency / deduplication&lt;/li&gt;
&lt;li&gt;support compensation / rollbacks for multi‑step flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an agentic system, that orchestration is often built on top of a governed capability runtime.&lt;/p&gt;

&lt;p&gt;Why pair a runtime with orchestration?&lt;/p&gt;

&lt;p&gt;A protocol‑neutral capability runtime gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schema‑validated inputs/outputs for each operation&lt;/li&gt;
&lt;li&gt;identity / ACL / approval checks&lt;/li&gt;
&lt;li&gt;structured traces and events per invocation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An orchestrator then uses those capabilities as building blocks, chaining them together under strong guarantees.&lt;/p&gt;

&lt;p&gt;The agent stays in the role of planner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it proposes which capabilities to call and with which parameters&lt;/li&gt;
&lt;li&gt;it can react to structured errors and adjust the plan&lt;/li&gt;
&lt;li&gt;it doesn’t try to be the persistence or retry layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation has practical benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Debuggability&lt;br&gt;
When a flow fails, you can see where: in planning, in runtime validation, or in orchestrated execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safety&lt;br&gt;
Every step is subject to the same ACLs, approvals, and audit behavior, regardless of whether it was triggered by an agent or a human.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evolution&lt;br&gt;
You can swap agent frameworks or tool protocols without rewriting the orchestration and governance layers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A small, realistic first step&lt;/p&gt;

&lt;p&gt;If you’re starting from an agent demo that calls services directly, you don’t have to refactor everything at once.&lt;/p&gt;

&lt;p&gt;Try this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pick a single, non‑trivial flow (e.g., canary deploy, batch data fix)&lt;/li&gt;
&lt;li&gt;expose the underlying operations as governed capabilities with schemas&lt;/li&gt;
&lt;li&gt;route all calls through a runtime that adds identity, ACLs, approvals, and traces&lt;/li&gt;
&lt;li&gt;have a simple orchestrator (queue + worker, or a workflow engine you already use) own retries and long‑running state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that path works, expand the set of capabilities and flows that use it.&lt;/p&gt;

&lt;p&gt;The key shift is mental: treat agents as planners on top of a governed, orchestrated system – not as replacements for the parts of your stack that already give you reliability guarantees.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Practical Patterns for AI Agent Governance in Production</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Wed, 07 Oct 2026 00:53:29 +0000</pubDate>
      <link>https://dev.to/tercelyi/practical-patterns-for-ai-agent-governance-in-production-3f84</link>
      <guid>https://dev.to/tercelyi/practical-patterns-for-ai-agent-governance-in-production-3f84</guid>
      <description>&lt;p&gt;When an AI agent starts calling real systems – deploy pipelines, billing, CRM, data workflows – “governance” stops being optional.&lt;/p&gt;

&lt;p&gt;Over the last year, a few practical patterns have emerged for teams that got agents into production without terrifying security and infra.&lt;/p&gt;

&lt;p&gt;Pattern 1: Treat capabilities as a catalog, not just functions&lt;/p&gt;

&lt;p&gt;Instead of wiring agents to ad‑hoc endpoints, define a capability catalog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stable capability IDs&lt;/li&gt;
&lt;li&gt;machine‑readable schemas for inputs and outputs&lt;/li&gt;
&lt;li&gt;metadata (owner, risk, environments)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same capabilities are callable by humans (CLI), services (HTTP/RPC), and agents. That shared catalog becomes your map of what the organization can actually do.&lt;/p&gt;

&lt;p&gt;Pattern 2: Build a centralized enforcement pipeline&lt;/p&gt;

&lt;p&gt;Sprinkling ACL checks and approvals across N services doesn’t scale.&lt;/p&gt;

&lt;p&gt;Introduce a runtime layer that every capability invocation passes through. It should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;resolve identity and caller context&lt;/li&gt;
&lt;li&gt;enforce ACLs&lt;/li&gt;
&lt;li&gt;evaluate approval conditions&lt;/li&gt;
&lt;li&gt;run middleware for logging / metrics / policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downstream services implement business logic; the runtime decides whether the call is allowed and how it should be wrapped.&lt;/p&gt;

&lt;p&gt;Pattern 3: Keep protocols as adapters on the edge&lt;/p&gt;

&lt;p&gt;MCP, HTTP, CLIs, internal RPC – all are just ways to reach the same capabilities.&lt;/p&gt;

&lt;p&gt;If each protocol carries its own governance semantics, you’ll get drift. Instead, let each protocol adapter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map protocol requests into capability calls&lt;/li&gt;
&lt;li&gt;inject identity and context&lt;/li&gt;
&lt;li&gt;route through the same enforcement pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That way, adopting a new tool protocol is mostly an adapter exercise, not a rewrite of core rules.&lt;/p&gt;

&lt;p&gt;Pattern 4: Evidence as a first‑class output&lt;/p&gt;

&lt;p&gt;When something breaks, teams want more than logs. They want evidence.&lt;/p&gt;

&lt;p&gt;Your runtime can emit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;structured “invocation” events (who, what, where)&lt;/li&gt;
&lt;li&gt;consistent error shapes with trace IDs&lt;/li&gt;
&lt;li&gt;hooks for usage / cost tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because this happens in one place, you don’t depend on every service getting logging exactly right.&lt;/p&gt;

&lt;p&gt;Pattern 5: Offload determinism to an orchestrator&lt;/p&gt;

&lt;p&gt;Agents are planners; they’re not great at guaranteeing that a fan‑out of 1,000 jobs completes exactly once.&lt;/p&gt;

&lt;p&gt;Pair agents with a workflow engine that handles determinism:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries and idempotency&lt;/li&gt;
&lt;li&gt;timeouts and cancellation&lt;/li&gt;
&lt;li&gt;compensation logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent assembles a plan in terms of governed capabilities; the orchestrator executes that plan reliably.&lt;/p&gt;

&lt;p&gt;Pattern 6: Iterate on one end‑to‑end path&lt;/p&gt;

&lt;p&gt;A realistic path for many teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pick a non‑trivial, high‑value capability (e.g., canary deploy)&lt;/li&gt;
&lt;li&gt;give it a schema, policies, and full tracing&lt;/li&gt;
&lt;li&gt;expose it to a human interface and an agent&lt;/li&gt;
&lt;li&gt;run it in production with tight monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use the friction you hit there to refine your runtime, then scale out to more capabilities.&lt;/p&gt;

&lt;p&gt;These patterns don’t depend on a specific framework. They do depend on drawing a clear line between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capabilities (what can be done)&lt;/li&gt;
&lt;li&gt;the governed runtime (who can do it, under what rules)&lt;/li&gt;
&lt;li&gt;protocols and agents (how it’s requested)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that separation exists, agent governance becomes a matter of evolving policy and runtime behavior – not rewriting every integration when a new agent pattern appears.&lt;/p&gt;

</description>
      <category>governance</category>
      <category>ai</category>
      <category>agents</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Raw Shell Access Is the Wrong Agent Integration—and What apexe Does Instead</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Thu, 01 Oct 2026 13:21:06 +0000</pubDate>
      <link>https://dev.to/tercelyi/why-raw-shell-access-is-the-wrong-agent-integration-and-what-apexe-does-instead-15c7</link>
      <guid>https://dev.to/tercelyi/why-raw-shell-access-is-the-wrong-agent-integration-and-what-apexe-does-instead-15c7</guid>
      <description>&lt;p&gt;Your organisation probably already owns the capabilities its agents need. They live in git, kubectl, jq, curl, operational scripts, and internal Unix command-line tools.&lt;/p&gt;

&lt;p&gt;The usual choice is uncomfortable: give an agent shell access, or rebuild every useful command as an API or MCP server.&lt;/p&gt;

&lt;p&gt;apexe is built for the middle path. It scans an existing CLI, turns each command into a schema-driven apcore module, and serves those modules through MCP or A2A with execution-time controls.&lt;/p&gt;

&lt;p&gt;existing CLI → module contract + reviewed policy → governed Executor → many agent clients&lt;br&gt;
What is supported today?&lt;br&gt;
Precision matters in agent infrastructure. The current product boundary is:&lt;/p&gt;

&lt;p&gt;Item    apexe 0.8 status&lt;br&gt;
Unix CLI tools on PATH  Supported by apexe scan&lt;br&gt;
macOS/Linux system utilities (ls, cat, cp, sort, …)   Supported as CLI tools, including BSD-aware parsing&lt;br&gt;
Built-in parsers (Man, BSD Usage, GNU, Click, Cobra, Clap)  Supported scanner feature&lt;br&gt;
ACL for scanned CLI modules Supported when supplied with --acl&lt;br&gt;
MCP Supported by apexe serve (stdio, HTTP, Explorer)&lt;br&gt;
A2A Supported by apexe a2a&lt;br&gt;
OpenAPI input   Not supported by the apexe CLI today&lt;br&gt;
OpenAPI deserves a direct note. The apcore toolkit has OpenAPI-related functionality, but apexe does not call its OpenAPIScanner. apexe is currently a CLI-to-agent bridge, so we should not market OpenAPI support as shipped functionality.&lt;/p&gt;

&lt;p&gt;Start with a real CLI&lt;br&gt;
apexe scan git curl jq&lt;br&gt;
apexe list&lt;br&gt;
apexe serve --show-config claude-desktop --acl ~/.apexe/acl.yaml&lt;br&gt;
The scan is deterministic: help text, man pages, and shell completions—not an LLM. It creates one binding per command, such as cli.git.log or cli.curl, and each binding contains JSON Schema for flags and operands.&lt;/p&gt;

&lt;p&gt;An agent calls a JSON object rather than composing a command string:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "url": "&lt;a href="https://httpbin.org/get" rel="noopener noreferrer"&gt;https://httpbin.org/get&lt;/a&gt;",&lt;br&gt;
  "silent": true&lt;br&gt;
}&lt;br&gt;
apexe validates this object, builds argv, and launches the program directly. No shell parses the resulting arguments.&lt;/p&gt;

&lt;p&gt;One capability configuration, many agent clients&lt;br&gt;
The goal is not to create a separate tool definition and security policy for every agent product. Bindings and ACL are the source of truth:&lt;/p&gt;

&lt;p&gt;~/.apexe/bindings/ + ~/.apexe/acl.yaml → apexe → Claude / Codex / Pi / another MCP client&lt;br&gt;
This does not mean every client shares one configuration-file format. Each host still needs its own MCP connection entry. What stays shared is the command or HTTP endpoint, the scanned module bindings, and the reviewed ACL.&lt;/p&gt;

&lt;p&gt;apexe can generate connection snippets for Claude Desktop and Cursor:&lt;/p&gt;

&lt;p&gt;apexe serve --show-config claude-desktop --acl ~/.apexe/acl.yaml&lt;br&gt;
apexe serve --show-config cursor --acl ~/.apexe/acl.yaml&lt;br&gt;
Codex can register the same local stdio server:&lt;/p&gt;

&lt;p&gt;codex mcp add apexe -- apexe serve --acl ~/.apexe/acl.yaml&lt;br&gt;
Pi and other MCP-capable clients can connect through their own MCP configuration mechanism. apexe does not currently generate a Pi-specific file, so the client must support the transport you select. For a shared deployment, run one authenticated HTTP server and have compatible clients connect to that endpoint.&lt;/p&gt;

&lt;p&gt;Why the module contract matters&lt;br&gt;
The contract is what lets the same capability retain its meaning across delivery surfaces:&lt;/p&gt;

&lt;p&gt;apexe serve exposes it over MCP, using stdio by default or HTTP with a browser Explorer.&lt;br&gt;
apexe a2a exposes the same governed modules as agent skills.&lt;br&gt;
--prefix and --tags reduce the registered surface before a client can discover or invoke it.&lt;br&gt;
Policy does not need to be rewritten per protocol because MCP and A2A share the same Executor.&lt;/p&gt;

&lt;p&gt;Governance is a product feature, not a checkbox&lt;br&gt;
apexe scan writes a default-deny ACL. It is a starter policy, not an invisible decision: enforcement begins only when an operator serves with --acl.&lt;/p&gt;

&lt;p&gt;apexe serve --acl ~/.apexe/acl.yaml&lt;br&gt;
The ACL controls which capability may be called. An always-on path guard answers a different question: what filesystem location may this specific call touch? It checks path-typed inputs after resolving symlinks and traversal, protects system paths from writes, and protects credential locations from both reads and writes.&lt;/p&gt;

&lt;p&gt;apexe policy&lt;br&gt;
apexe policy --path /etc/nginx/conf.d --mode write&lt;br&gt;
Every child process is shell-free, runs with a scrubbed environment, has a timeout and output cap, and can produce a private audit record. These are meaningful safeguards, but they are not a sandbox. Run exposed tools inside the container, VM, account, and network boundary your risk model requires.&lt;/p&gt;

&lt;p&gt;Why 0.7 and 0.8 matter&lt;br&gt;
The current releases make the boundary more useful in practice: path protection, argument-sensitive approvals, refusal of verified command-executing parameters, binary availability checks, an explicit default-deny tier for network-reaching tools, and externally maintained verified CLI overlays.&lt;/p&gt;

&lt;p&gt;Bindings now live by default under ~/.apexe/bindings and record which apexe version produced them. Existing users should rescan after upgrading:&lt;/p&gt;

&lt;p&gt;apexe scan git curl jq --no-cache&lt;br&gt;
apexe list --available-only&lt;br&gt;
What comes next: local execution, then native terminal workflows&lt;br&gt;
The next proposed feature is F8 local execution. It is deliberately split into two stages rather than treating a shell wrapper as a shortcut.&lt;/p&gt;

&lt;p&gt;Stage 1, apexe run, is a structured local entry point for one scanned module at a time:&lt;/p&gt;

&lt;p&gt;apexe run cli.ls --input '{"long": true, "paths": ["/tmp"]}' --acl ~/.apexe/acl.yaml&lt;br&gt;
It will reuse the same Executor that MCP and A2A use, produce captured output, and make preflight decisions inspectable from the terminal. It is not native shell syntax and does not provide streaming stdin or pipelines.&lt;/p&gt;

&lt;p&gt;Stage 2, apexe env with PATH shims, is the intended end-user terminal experience. Eligible external commands retain their normal names and argv syntax, so an existing pipeline such as ls -l /tmp | grep ERROR | head -20 can remain unchanged. Each stage is independently resolved to a scanned module and receives schema validation, verified cli-permissions facts, ACL, path guard, timeout, output limit, and audit logging—without using sh -c.&lt;/p&gt;

&lt;p&gt;This is not available yet. Its safety depends on contracts that are still being settled: passthrough I/O, an explicit human-reviewed allowlist for modules that may read streaming stdin, PATH isolation, and measurements of refusal rate and shim latency. It also cannot intercept shell builtins, aliases/functions, or absolute-path calls. Read the F8 design for the exact boundary.&lt;/p&gt;

&lt;p&gt;Join the design conversation&lt;br&gt;
The interesting question is not “can an agent run a command?” It can. The question is which existing capability sources should share a contract, governance layer, and protocol delivery model.&lt;/p&gt;

&lt;p&gt;We would love your comments:&lt;/p&gt;

&lt;p&gt;Which CLI or internal tool would you expose first?&lt;br&gt;
Which agent hosts—Claude, Codex, Pi, or another MCP client—need the same governed tool surface?&lt;br&gt;
Which existing scripts or pipelines should a governed PATH-shim mode support first?&lt;br&gt;
Would OpenAPI ingestion be valuable in the same workflow?&lt;br&gt;
What must an operator review before an agent can use a newly discovered capability?&lt;br&gt;
Project: aiperceivable/apexe&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>cli</category>
      <category>seurity</category>
    </item>
    <item>
      <title>Designing Schema-First Capabilities for AI Agents</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Thu, 01 Oct 2026 05:49:02 +0000</pubDate>
      <link>https://dev.to/tercelyi/designing-schema-first-capabilities-for-ai-agents-fpn</link>
      <guid>https://dev.to/tercelyi/designing-schema-first-capabilities-for-ai-agents-fpn</guid>
      <description>&lt;p&gt;If your AI agent can call production systems, the contract between the agent and your capabilities is more important than the prompt.&lt;/p&gt;

&lt;p&gt;A schema‑first capability design puts that contract at the center of your architecture and lets everything else – CLIs, HTTP APIs, agent tools – project from it.&lt;/p&gt;

&lt;p&gt;What is a schema‑first capability?&lt;/p&gt;

&lt;p&gt;Take a real operation in your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create_invoice&lt;/li&gt;
&lt;li&gt;deploy_service&lt;/li&gt;
&lt;li&gt;reset_user_password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of documenting this informally and wiring it directly into APIs, you define a machine‑readable schema that captures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;input fields, types, and constraints&lt;/li&gt;
&lt;li&gt;output structure&lt;/li&gt;
&lt;li&gt;error variants and their shapes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This schema is authoritative across all callers: humans, microservices, and AI agents.&lt;/p&gt;

&lt;p&gt;Why do this for agents?&lt;/p&gt;

&lt;p&gt;LLMs are not type‑safe. They will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;omit required fields&lt;/li&gt;
&lt;li&gt;invent new ones&lt;/li&gt;
&lt;li&gt;send wrong types ("five" instead of 5)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you validate deep inside your application, you only discover problems after partial side effects. A schema‑aware runtime can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validate inputs before execution&lt;/li&gt;
&lt;li&gt;validate outputs before returning&lt;/li&gt;
&lt;li&gt;produce structured errors the agent can learn to handle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That alone dramatically reduces “mystery failures” in production.&lt;/p&gt;

&lt;p&gt;Schema as a governance anchor&lt;/p&gt;

&lt;p&gt;Once every capability has a stable ID and schema, you can attach policy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which identities / roles may call it&lt;/li&gt;
&lt;li&gt;which calls need approval&lt;/li&gt;
&lt;li&gt;which environments it applies to&lt;/li&gt;
&lt;li&gt;what logging, tracing, and usage hooks must run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crucially, this policy is attached to the capability itself, not to any single protocol.&lt;/p&gt;

&lt;p&gt;Multi‑language, one contract&lt;/p&gt;

&lt;p&gt;Most organizations run Python, TypeScript, and at least one systems language. A normative schema lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generate / validate language‑specific SDKs&lt;/li&gt;
&lt;li&gt;write conformance tests once&lt;/li&gt;
&lt;li&gt;keep contracts synchronized across stacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents don’t care which language implements a capability; they care that the contract is consistent.&lt;/p&gt;

&lt;p&gt;A concrete pattern to start&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose an existing, non‑trivial operation.&lt;/li&gt;
&lt;li&gt;Write its real input/output contract and error cases.&lt;/li&gt;
&lt;li&gt;Encode that as a schema.&lt;/li&gt;
&lt;li&gt;Wrap the implementation in a small runtime layer that validates against the schema and emits structured events.&lt;/li&gt;
&lt;li&gt;Expose it through one additional surface (CLI, HTTP, or a tool protocol).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Measure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how often validation catches bad calls&lt;/li&gt;
&lt;li&gt;how much easier debugging becomes with structured traces&lt;/li&gt;
&lt;li&gt;how straightforward it is to add another surface once the capability exists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over time, your catalog of schema‑first capabilities becomes the safe surface area your agents can operate in, with the same rules and evidence as the rest of your stack.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>What a Governed Agent Runtime Actually Does</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Tue, 29 Sep 2026 01:33:25 +0000</pubDate>
      <link>https://dev.to/tercelyi/what-a-governed-agent-runtime-actually-does-31aa</link>
      <guid>https://dev.to/tercelyi/what-a-governed-agent-runtime-actually-does-31aa</guid>
      <description>&lt;p&gt;Most AI agent prototypes fail not because the model is weak, but because the path from the model to real capabilities is essentially ungoverned.&lt;/p&gt;

&lt;p&gt;When an agent can deploy code, mutate data, or touch infrastructure, you need more than tool definitions. You need a governed runtime between the model and the capability.&lt;/p&gt;

&lt;p&gt;In this article I’ll outline what a governed, protocol‑neutral runtime does, why it matters for AI agents, and how it differs from agent frameworks and tool protocols.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start from capabilities, not protocols&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In many stacks, the starting point is the protocol surface: an HTTP API, a CLI, an MCP server, or a bespoke RPC layer. Governance ends up scattered across them.&lt;/p&gt;

&lt;p&gt;A governed runtime inverts this. The primitive is a capability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a function your system can perform&lt;/li&gt;
&lt;li&gt;with a strict input/output schema&lt;/li&gt;
&lt;li&gt;annotated with metadata and policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Protocols become adapters that project that same capability to different callers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enforce strict contracts at the edge&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;LLMs are probabilistic. They will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;omit required fields&lt;/li&gt;
&lt;li&gt;invent parameters&lt;/li&gt;
&lt;li&gt;send values in the wrong shape&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only validate deep inside application code, you pay for side effects and partial failures before discovering the problem.&lt;/p&gt;

&lt;p&gt;A governed runtime enforces contracts before execution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validate inputs against a schema&lt;/li&gt;
&lt;li&gt;validate outputs before returning&lt;/li&gt;
&lt;li&gt;guarantee error shapes so callers can rely on them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is just as important for human‑driven CLI or HTTP calls as it is for agents.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Centralize governance semantics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When every surface (CLI, HTTP, MCP, a2a) re‑implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ACL checks&lt;/li&gt;
&lt;li&gt;approval workflows&lt;/li&gt;
&lt;li&gt;environment / tenant routing&lt;/li&gt;
&lt;li&gt;logging and policy hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…you end up with drift and blind spots.&lt;/p&gt;

&lt;p&gt;A runtime should provide a single pipeline where it can apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identity and ACL resolution&lt;/li&gt;
&lt;li&gt;approval gates for high‑risk actions&lt;/li&gt;
&lt;li&gt;call‑chain guards (who called on behalf of whom)&lt;/li&gt;
&lt;li&gt;middleware for custom policies and observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adapters then plug into that pipeline, instead of embedding their own partial implementation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make execution observable by default&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Governed systems need more than a log line. They need structured evidence.&lt;/p&gt;

&lt;p&gt;A runtime can emit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;structured errors tied to capability IDs&lt;/li&gt;
&lt;li&gt;trace context that spans agent reasoning and execution&lt;/li&gt;
&lt;li&gt;events (started, retried, completed, failed)&lt;/li&gt;
&lt;li&gt;usage hooks suitable for metrics and billing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes capabilities safe to expose through multiple channels, because you can audit and debug behavior no matter who called them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Separate reasoning from orchestration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Agent frameworks excel at planning and choosing tools, not at guaranteeing exactly‑once execution across a fleet of workers.&lt;/p&gt;

&lt;p&gt;A robust design pairs the governed runtime with a workflow / orchestration layer that handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;distributed task execution&lt;/li&gt;
&lt;li&gt;retries, backoff, and idempotency&lt;/li&gt;
&lt;li&gt;timeouts and cancellation&lt;/li&gt;
&lt;li&gt;compensation logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent chooses; the runtime and orchestrator guarantee how.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stay protocol‑neutral&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Today’s hot protocol is MCP. Tomorrow it might be something else.&lt;/p&gt;

&lt;p&gt;If all your semantics live in one protocol layer, you’re locked in. A protocol‑neutral runtime keeps your:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;schemas&lt;/li&gt;
&lt;li&gt;governance&lt;/li&gt;
&lt;li&gt;execution semantics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…independent of any single protocol. MCP, a2a bridges, CLIs, HTTP APIs, and in‑process calls all project the same capability definition.&lt;/p&gt;

&lt;p&gt;What to look for in a governed agent runtime&lt;/p&gt;

&lt;p&gt;When you evaluate libraries and platforms, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where do capability contracts live, and are they language‑agnostic?&lt;/li&gt;
&lt;li&gt;How are identity, ACLs, and approvals enforced?&lt;/li&gt;
&lt;li&gt;Can I expose the same capability to MCP, HTTP, CLI, and internal code without rewriting logic?&lt;/li&gt;
&lt;li&gt;What structured evidence do I get when something goes wrong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A runtime that answers those questions cleanly will make your agents safer, more debuggable, and easier to operate in production than yet another pile of glue code between an LLM and your systems.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>devtools</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Cross-Language SDKs for a Single Agent Capability Standard</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Thu, 10 Sep 2026 08:05:30 +0000</pubDate>
      <link>https://dev.to/tercelyi/cross-language-sdks-for-a-single-agent-capability-standard-2hn8</link>
      <guid>https://dev.to/tercelyi/cross-language-sdks-for-a-single-agent-capability-standard-2hn8</guid>
      <description>&lt;p&gt;In most real-world systems, “AI agents” sit on top of a polyglot stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python for data and ML&lt;/li&gt;
&lt;li&gt;TypeScript/Node for backend and APIs&lt;/li&gt;
&lt;li&gt;Rust/Go for performance-sensitive pieces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your capability model only really exists in one language, you end up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate logic in other languages&lt;/li&gt;
&lt;li&gt;Inconsistent validation and error handling&lt;/li&gt;
&lt;li&gt;Governance rules that only apply to the Python part&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A more sustainable pattern is to treat the &lt;strong&gt;capability protocol&lt;/strong&gt; as the primary artifact and the language SDKs as implementations.&lt;/p&gt;

&lt;p&gt;Concretely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Specify a wire-level protocol and schema format.&lt;/li&gt;
&lt;li&gt;Define how metadata (risk, cost, ownership) and governance hooks (ACL, approvals, audit) attach to a capability.&lt;/li&gt;
&lt;li&gt;Build SDKs in your target languages that:

&lt;ul&gt;
&lt;li&gt;Use the same conformance tests&lt;/li&gt;
&lt;li&gt;Expose idiomatic APIs&lt;/li&gt;
&lt;li&gt;Produce identical runtime behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now a capability implemented in Rust can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Called by a Python-based agent&lt;/li&gt;
&lt;li&gt;Exposed as an HTTP endpoint by a TypeScript service&lt;/li&gt;
&lt;li&gt;Invoked via CLI by ops teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…without reinventing validation, approvals, or tracing.&lt;/p&gt;

&lt;p&gt;If you are designing your own internal runtime, consider starting with the protocol and tests first, and only then layering language-specific ergonomics on top. It is slower upfront but pays off when your stack inevitably becomes polyglot.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Designing Directory-as-ID for AI-Discoverable Capabilities</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Thu, 03 Sep 2026 05:11:23 +0000</pubDate>
      <link>https://dev.to/tercelyi/designing-directory-as-id-for-ai-discoverable-capabilities-3pcb</link>
      <guid>https://dev.to/tercelyi/designing-directory-as-id-for-ai-discoverable-capabilities-3pcb</guid>
      <description>&lt;p&gt;Capability discovery is one of those problems that quietly gets solved five different ways in the same company.&lt;/p&gt;

&lt;p&gt;For AI agents it matters even more: if you cannot reliably discover and describe your own capabilities, models will not either.&lt;/p&gt;

&lt;p&gt;A simple, robust pattern is &lt;strong&gt;directory-as-ID&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The directory path on disk &lt;em&gt;is&lt;/em&gt; the capability identifier.&lt;/li&gt;
&lt;li&gt;A schema + metadata file live alongside the implementation.&lt;/li&gt;
&lt;li&gt;The runtime walks the tree to build a catalog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why this helps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Natural for developers&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Your repo already uses directory structure to organize concepts. Making it the capability ID means &lt;code&gt;git diff&lt;/code&gt;, code review, and grep remain your primary tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Good for governance&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
ACLs and approval rules can be attached at directory boundaries (e.g., &lt;code&gt;payments/*&lt;/code&gt; requires stronger checks than &lt;code&gt;analytics/*&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Legible to AI systems&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Models (or offline indexers) can infer semantics from stable paths and read schemas/metadata without custom discovery code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A minimal implementation looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;capabilities/
payments/charge/
  schema.json
  metadata.yaml
  implementation.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recursively walks &lt;code&gt;capabilities/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Loads schema + metadata.&lt;/li&gt;
&lt;li&gt;Registers the capability under the directory path as ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From there you can project the same capability into MCP tools, HTTP endpoints, CLIs, or direct imports—with governance hanging off the catalog instead of scattered across services.&lt;/p&gt;

&lt;p&gt;If you are wrestling with “how do I let agents discover what they can safely do?”, directory-as-ID is a surprisingly powerful starting constraint.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developer</category>
      <category>architecture</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Why Your AI Agent Keeps Calling the Wrong Tool (and How to Fix It)</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Tue, 01 Sep 2026 01:24:47 +0000</pubDate>
      <link>https://dev.to/tercelyi/why-your-ai-agent-keeps-calling-the-wrong-tool-and-how-to-fix-it-afj</link>
      <guid>https://dev.to/tercelyi/why-your-ai-agent-keeps-calling-the-wrong-tool-and-how-to-fix-it-afj</guid>
      <description>&lt;p&gt;It’s Friday afternoon. You’ve just deployed a sophisticated AI Agent with a suite of 50 enterprise tools. Five minutes later, the logs show a disaster: the Agent was supposed to deactivate_user for a support ticket, but instead, it hallucinated and called delete_user.&lt;br&gt;
Why? Because the text descriptions were "too similar," and the LLM felt lucky.&lt;br&gt;
If you’ve spent any time building Agentic systems, you know this pain. We’ve been building mission-critical automation on top of "Vibes"—fuzzy string descriptions and loose JSON objects.&lt;br&gt;
Let’s look at why traditional tool-calling is failing and how we can move toward a world of AI-Perceivable modules.The "Vibe-Based" Engineering Crisis&lt;/p&gt;

&lt;p&gt;On the surface, this looks fine. But as your system scales from 5 tools to 50 or 500, several critical failure points emerge:- Description Overlap: If you have remove_user, delete_account, and deactivate_member, the LLM often picks the wrong one based on a slight nuance in the user's prompt.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No Behavioral Context: Does the AI know that delete_user is a destructive operation that should require human approval? No. It just sees a string.&lt;/li&gt;
&lt;li&gt;The Validation Gap: Traditional tools are often "fire and forget." If the AI passes a malformed ID, the system throws a generic 500 error, and the Agent gets stuck in a loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are essentially trying to "Prompt Engineer" our way into reliable software. That is not engineering; that’s hope.Introducing apcore: The AI-Perceivable Standard&lt;br&gt;
At apcore, we believe that if a module is to be invoked by an AI, it must be AI-Perceivable. This means the module must explicitly communicate its structure, its behavior, and its constraints in a way that the AI doesn't have to "guess."&lt;br&gt;
Let's look at the same delete_user tool implemented as an apcore module in Python:&lt;br&gt;
from apcore import Module, ModuleAnnotations, Context&lt;br&gt;
from pydantic import BaseModel, &lt;br&gt;
Why this is a game-changer:- Dual-Layered Intelligence: We separate the description (short, for discovery) from the documentation (long, for detailed planning). The AI only reads the "manual" when it's actually considering using the tool.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Behavioral Guardrails: By marking a module as destructive, we give the LLM a cognitive "stop sign." It knows it shouldn't just run this autonomously.&lt;/li&gt;
&lt;li&gt;Strict Enforcement: In apcore, you cannot register a module without a valid schema. It turns "AI-Perceivability" from a best practice into a protocol requirement.
The Secret Sauce: ai_guidance
What happens when the AI does make a mistake? In traditional systems, you get a traceback. In apcore, we use Self-Healing Guidance.
If an Agent sends a numeric ID instead of a UUID to our delete_user module, apcore doesn't just crash. It returns a structured error:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Agent reads the ai_guidance, realizes its mistake, fetches the correct UUID, and retries—autonomously. This is the path to truly resilient Agentic systems.Conclusion: Stop Prompting, Start Engineering&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>Type-Safe Agents: Leveraging apcore-js in TypeScript</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Sat, 06 Jun 2026 12:32:25 +0000</pubDate>
      <link>https://dev.to/tercelyi/type-safe-agents-leveraging-apcore-js-in-typescript-2447</link>
      <guid>https://dev.to/tercelyi/type-safe-agents-leveraging-apcore-js-in-typescript-2447</guid>
      <description>&lt;p&gt;While Python dominates the AI research space, TypeScript is the engine of the modern full-stack web. From high-performance Node.js backends to complex React frontends, TypeScript provides the structure and safety that large-scale engineering teams demand.&lt;/p&gt;

&lt;p&gt;When we built the &lt;strong&gt;apcore-js&lt;/strong&gt; SDK, we didn't just want to "port" the Python logic. We wanted to create a first-class, type-safe experience that leverages the unique strengths of the JavaScript ecosystem. &lt;/p&gt;

&lt;p&gt;In this twentieth article of our series, we explore how to build AI-Perceivable modules in TypeScript using apcore and &lt;strong&gt;TypeBox&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Goal: Cross-Language Parity
&lt;/h2&gt;

&lt;p&gt;A core tenet of the apcore protocol is that a module’s behavior should be identical regardless of the implementation language. A module named &lt;code&gt;executor.user.get&lt;/code&gt; must accept the same JSON input and produce the same output in both Python and TypeScript.&lt;/p&gt;

&lt;p&gt;apcore-js achieves this by using &lt;strong&gt;TypeBox&lt;/strong&gt; as its core schema engine. TypeBox allows us to define JSON Schemas that double as TypeScript types, giving us compile-time safety and runtime validation in a single definition.&lt;/p&gt;




&lt;h2&gt;
  
  
  Defining Type-Safe Schemas
&lt;/h2&gt;

&lt;p&gt;In apcore-js, you define your module's contract using TypeBox's &lt;code&gt;Static&lt;/code&gt; and &lt;code&gt;Type&lt;/code&gt; primitives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Static&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sinclair/typebox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;InputSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The unique UUID of the user.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;includePrivate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Whether to include sensitive fields.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Static&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;InputSchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding the &lt;code&gt;description&lt;/code&gt; field directly into the TypeBox definition, you are creating the "Cognitive Interface" for the AI while simultaneously providing type hints for your IDE.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the Module
&lt;/h2&gt;

&lt;p&gt;apcore-js supports both class-based and functional module definitions. The class-based approach is idiomatic for TypeScript developers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ClassModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleAnnotations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apcore/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetUserModule&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ClassModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executor.user.get&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Retrieve detailed user profiles.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;inputSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;InputSchema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ModuleAnnotations&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;destructive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// inputs is fully typed!&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Automated Discovery &amp;amp; Mapping
&lt;/h2&gt;

&lt;p&gt;Managing a registry in Node.js is just as easy as in Python. apcore-js includes a &lt;code&gt;FileSystemLoader&lt;/code&gt; that scans your directory structure.&lt;/p&gt;

&lt;p&gt;One of the cleverest parts of the SDK is its &lt;strong&gt;Automatic ID Normalization&lt;/strong&gt;. In TypeScript, it’s common to name your files using &lt;code&gt;camelCase&lt;/code&gt; (e.g., &lt;code&gt;sendEmail.ts&lt;/code&gt;). apcore-js automatically maps this to the canonical &lt;code&gt;snake_case&lt;/code&gt; (e.g., &lt;code&gt;send_email&lt;/code&gt;) required by the protocol. This ensures that an AI Agent sees a consistent naming convention even in a polyglot environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trace Propagation in the Node Mesh
&lt;/h2&gt;

&lt;p&gt;AI Agents in the Node ecosystem often live inside microservices. apcore-js is built for distributed environments. It automatically propagates the &lt;code&gt;trace_id&lt;/code&gt; through &lt;code&gt;Promise&lt;/code&gt; chains and can integrate with existing tracing headers (like Zipkin or Jaeger) via custom middleware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executor.user.get&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion: Reliability at Compile Time
&lt;/h2&gt;

&lt;p&gt;By combining the rigor of the apcore protocol with the safety of TypeScript and TypeBox, &lt;strong&gt;apcore-js&lt;/strong&gt; allows you to build AI-Perceivable systems that are as reliable as they are intelligent. You get the best of both worlds: high-velocity development and rock-solid architectural constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now that we’ve mastered the two most popular languages for AI, it’s time to look at the performance tier. In our next article, we dive into Zero-Cost Abstraction: Building High-Performance AI Modules in Rust.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is Article #20 of the **Building the AI-Perceivable World&lt;/em&gt;* series. Type safety is the first step to AI safety.*&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/aiperceivable/apcore-typescript" rel="noopener noreferrer"&gt;aiperceivable/apcore-typescript&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Pythonic AI: Mastering the apcore-python SDK</title>
      <dc:creator>tercel</dc:creator>
      <pubDate>Wed, 03 Jun 2026 12:36:55 +0000</pubDate>
      <link>https://dev.to/tercelyi/pythonic-ai-mastering-the-apcore-python-sdk-5da8</link>
      <guid>https://dev.to/tercelyi/pythonic-ai-mastering-the-apcore-python-sdk-5da8</guid>
      <description>&lt;p&gt;Python is the undisputed language of the AI era. It’s the language of research, the language of LLM orchestration (LangChain, CrewAI), and for many, the language of the enterprise backend. &lt;/p&gt;

&lt;p&gt;When we designed the &lt;strong&gt;apcore-python&lt;/strong&gt; SDK, our goal was simple: &lt;strong&gt;High Perceptibility, Low Intrusion.&lt;/strong&gt; We wanted to give Python developers a way to make their code "AI-ready" without forcing them to rewrite their entire architecture.&lt;/p&gt;

&lt;p&gt;In this nineteenth article of our series, we move from the engine room to the keyboard, showing you how to master the Python SDK to build professional, AI-Perceivable modules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Defining Modules: The Two Styles
&lt;/h2&gt;

&lt;p&gt;Every developer has a different preference. Some love the structure of classes; others prefer the simplicity of decorators. apcore supports both.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Decorator Style (Fast &amp;amp; Functional)
&lt;/h3&gt;

&lt;p&gt;If you have an existing utility function and you want to turn it into an AI "Skill" in 30 seconds, use the &lt;code&gt;@module&lt;/code&gt; decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apcore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;

&lt;span class="nd"&gt;@module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text.summarize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize text for Agentic planning.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Your logic here...
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The Class Style (Structured &amp;amp; Extensible)
&lt;/h3&gt;

&lt;p&gt;For modules that require complex state, custom initialization, or detailed behavioral annotations, the class-based approach is superior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apcore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ModuleAnnotations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendEmailInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendEmailModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;input_schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SendEmailInput&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Send secure internal emails.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;annotations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModuleAnnotations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destructive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requires_approval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Business logic...
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pydantic Integration: The Secret Weapon
&lt;/h2&gt;

&lt;p&gt;The "Killer Feature" of apcore-python is its deep integration with &lt;strong&gt;Pydantic V2&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In the AI world, your schema's &lt;code&gt;description&lt;/code&gt; fields are just as important as the types. apcore-python extracts these descriptions directly from your Pydantic models.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(...,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The search term. Use keywords, not sentences.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max results to return.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you register this module, apcore automatically generates a JSON Schema Draft 2020-12 that includes these descriptions. This ensures that the AI Agent knows exactly &lt;em&gt;how&lt;/em&gt; to use each parameter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Initializing the Core
&lt;/h2&gt;

&lt;p&gt;Starting with &lt;strong&gt;v0.18.0&lt;/strong&gt;, we’ve simplified the &lt;code&gt;APCore&lt;/code&gt; constructor to focus on a unified configuration model. You no longer pass multiple paths to the constructor; instead, you load a &lt;code&gt;Config&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apcore&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APCore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;

&lt;span class="c1"&gt;# Load config from apcore.yaml and initialize
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apcore.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that your security policies, pipeline steps, and registry settings are always in sync across your entire application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Execution &amp;amp; Async Support
&lt;/h2&gt;

&lt;p&gt;AI Agents are often used in asynchronous environments (web servers, background tasks). The apcore-python SDK is built for this. You can call modules synchronously or asynchronously with full trace propagation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Async execution with identity propagation
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text.summarize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion: Built for Developers, Ready for AI
&lt;/h2&gt;

&lt;p&gt;apcore-python isn't just a library; it’s a design pattern. It allows you to build software that is idiomatic for Python developers and perfectly perceivable by AI Agents. By combining the power of Pydantic with the rigor of the apcore protocol, you are building the foundation for a reliable Agentic workforce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now that we’ve mastered Python, it’s time to look at the other side of the stack. In our next article, we dive into Type-Safe Agents: Leveraging apcore-js in TypeScript.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is Article #19 of the **Building the AI-Perceivable World&lt;/em&gt;* series. Idiomatic code is the bridge to better AI.*&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/aiperceivable/apcore-python" rel="noopener noreferrer"&gt;aiperceivable/apcore-python&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
