跳到正文
DEV Community· Fabian Graßl·· 3 小時前AI 評分37

為何以 PHP 建構 AI 智能體 harness?

Why build an agent harness in PHP?

AI 導讀

Spora 以 PHP 編寫智能體 harness,選擇 PHP 是為了讓工具可在共享主機、廉價 VPS 等環境運行。Spora-core 只需 PHP 8.4.1 和標準擴展,預設使用 SQLite,生產環境以 MySQL 為目標,毋須 Redis、訊息代理、Node 建置步驟或編排器。每個 tick 在單次請求內載入狀態、呼叫模型並記錄決策,狀態存入資料庫,讓工作可在長時間等待批准後續行。

正文

Skip to content

Image 1: DEV Community

Powered by Algolia

Log inCreate account

DEV Community

Image 2 Add reaction

Image 3 Like Image 4 Unicorn Image 5 Exploding Head Image 6 Raised Hands Image 7 Fire

Jump to Comments Save Boost

Pick as gem

Copy link

Copied to Clipboard

Share to XShare to LinkedInShare to FacebookShare to Mastodon

Share Post via...Report Abuse

Image 8: Fabian Graßl

Fabian Graßl Posted on Oct 29•Originally published at spora-ai.com•AI-assisted

Why build an agent harness in PHP?

#ai#php#webdev#programming

Spora's agent harness is written in PHP. That is not the obvious choice. Most agent tooling is Python, and PHP is what people reach for when they want a website, not a system that talks to a model.

I picked it anyway. Four reasons, none of them about the language itself — and one constraint that turned out to be the reason the rest of it works.

The constraint: PHP's default is one request, one response

The default way to run PHP is a request/response loop: PHP-FPM starts a process, serves one request, and tears it down. A good model for a web page, an awkward one for an agent, which thinks for eight seconds and then wants to hold a socket open while it streams tokens.

PHP can do real-time, and Spora does it where it makes sense — the Docker image runs FrankenPHP, the full deployment adds a Mercure hub, and worker:run --daemon is a long-lived PHP process. But none of that is the default. It is a different deployment than "copy the files up", and on a shared host some of it is not available at all.

So Spora is built for the default rather than against it. A tick is one LLM turn: load the state, call the model, record what it decided, decide whether a human has to approve the next step. It all happens inside one request, and when that request ends, the state is in the database.

That reads like a limitation for a streaming UI. It is exactly the shape an agent harness needs. Approving a write is not fast — it might take four minutes, or overnight, or three days. A tick that ends in a durable state transition is the right primitive for a step that can pause that long: nothing lives in memory, nothing is lost when a process dies, and the next tick resumes exactly where the last one stopped. You approve a tool call on Monday; the agent continues on Tuesday.

Where you want more than the default, Spora has three configurations, split along two axes — who runs the worker, and how the UI hears about it:

  • Full Deployment — a server daemon drains the queue, Mercure pushes updates over server-sent events. Docker and VPS; the only one where the interface is instant.
  • Classical Server — the same daemon without Mercure, so the frontend polls every five seconds instead. A plain LAMP host with shell access.
  • Zero-Config Shared Host — no daemon: the browser is the worker. A SharedWorker, shared across that browser's tabs, ticks the logged-in user's own tasks every two seconds. Upload the files, point the document root at public/, log in.

The third one carries the honest cost of a $5 host: with no daemon, scheduled runs only dispatch while a browser is open. That is what you pay for needing nothing but FTP.

Four reasons to build the harness in PHP

It hosts where the users are

The person who wants to run their own AI infrastructure is usually a developer or a two-person team with a shared cPanel account, a cheap VPS, or a Raspberry Pi — not a platform team with a Kubernetes budget.

Spora-core needs PHP 8.4.1 and the standard extensions. That is the whole list. The install is composer create-project spora-ai/spora, then php bin/spora spora:install. SQLite is the default database and MySQL is the production target. There is no Redis, no broker, no Node build step, no orchestrator. Anyone who has set up a WordPress site can already run Spora.

Compare that with the deployment floor of the obvious alternatives. A Python service means a virtualenv, a process supervisor, a reverse proxy and a systemd unit — fine for a backend team, a dealbreaker for this one. A Go or Rust service means a build pipeline plus a binary that has to match the host's libc. PHP files are files: FTP them up and they run.

Plugins install while the system is running

A Spora plugin is an ordinary Composer package with a plugin.json manifest. The installer routes it into plugins/<name>/, and Composer resolves its dependencies like any other package — so a plugin that needs an HTTP client or a PDF parser just requires it, and the solver handles the rest.

Because it is only Composer, installing does not need a redeploy. php bin/spora plugin:install vendor/name does it from the CLI, and with SPORA_PLUGIN_INSTALL_ENABLED turned on, the admin UI can browse a Packagist catalog and install, update or remove plugins against the running system.

It is opt-in for a reason: the installer runs a Composer binary as an external command, and the published Docker image does not ship one. Turn the flag on where a Composer binary exists, and leave it off where it does not.

The model already knows the language

Here is the argument I did not expect to make. 69.2% of the websites with a known server-side language run PHP, and the great majority of those already run version 8 (W3Techs, October 2026). That is an enormous amount of public PHP — and public PHP is what a model trained on code has seen most of, in this family of languages.

It shows up in the output. Ask a model for a PHP class and it produces conventions that match the ecosystem: PSR-4 namespacing, a Composer manifest with the right keys, Symfony-style dependency injection, an Eloquent model instead of a hand-rolled repository. Not because anybody told it to — because that is what the training data looks like.

If your agent writes code or plugins for you, the language it writes best is the one with the most code in the corpus. PHP may not be the language agent tooling is built in, but it is the one models write with surprising fluency.

The integration ecosystem is already solved

Packagist lists more than 300,000 packages. The integrations an agent harness needs — payments, mail, storage, OAuth, translation, PDF, image processing — are not a research project. They are a composer require away, already versioned, already maintained, already compatible with the PHP version you already run.

Spora-core leans on exactly that: symfony/http-client for talking to APIs, symfony/mailer for mail, illuminate/database for the database, nikic/fast-route for routing, php-di/php-di for the container, league/commonmark for Markdown. Every one of those is a solved problem maintained by people whose full-time job is that problem. A harness that needs an SMTP client should not be writing one.

This is also why there is no language barrier for plugin authors. If you can write a PHP class, you can write a Spora plugin.

What I gave up

  • Concurrency inside a single turn. PHP's request/response model has no event loop, so the tool calls inside one LLM turn run in sequence rather than side by side. Agents already run in parallel; it is the fan-out within a turn that is serial today. PHP has had native Fibers since 8.1, and Swoole is a single extension away - one that most shared hosts do not offer. Parallel tool calls are on the roadmap. Shipping the simple version first is deliberate: the point of the first release is that a developer can install it and watch an agent work, not that it benchmarks fastest.
  • Runtime plugin installs need a writable disk and a Composer binary. Both are ordinary, and both are occasionally missing on shared hosting.
  • The AI ecosystem pulls developers toward Python and TypeScript. PHP is the largest server-side language there is, so the size of the pool is not the problem. The part of that pool that wants to build AI tooling is not bigger for being PHP, though. Agent work pulls people in from the Python and TypeScript side, and they do not arrive at PHP by default.

What I expected to give up

Streaming was the one I expected to lose. Task updates are already pushed over server-sent events, and the tick model does not stand in the way of pushing more of them. Streaming the model's own output, token by token, is the next milestone: the drivers would gain an optional streaming mode, and Mercure already provides the SSE pipeline to carry it — a step on top of what exists rather than a new subsystem.

Tooling is the other. Python is not a decade ahead of PHP for server-side work: PHPStan and Larastan find real bugs, Pest is a first-class test framework, Rector and PHP-CS-Fixer cover the mechanical edits, and FrankenPHP is a modern app server. The gap that is left is the data stack — notebooks, NumPy, the scientific libraries — and an orchestration layer has no use for any of it.

The rule I used

Pick the language whose deployment reality matches your users' deployment reality. Spora's users run their own infrastructure, on cheap hosts, extending it themselves with plugins. PHP is the only language where the host, the user and the runtime already agree on what deployment means.

The second rule is less obvious: the language's default should be the thing your product does not need. PHP's default is that a request ends and the process goes away. An agent harness that waits for a human to approve a write wants exactly that: the step ends, the state is durable, and nothing is held open waiting for the model to change its mind.

If you want to see whether that holds up in practice, install Spora and tick it yourself. If you would rather start with a plugin, the plugin skeleton is about eighty lines of PHP.

Top comments (0)

Subscribe

Image 9: pic

Personal Trusted UserCreate template Templates let you quickly answer FAQs or store snippets for re-use.

Submit PreviewDismiss

Code of Conduct•Report abuse

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink.

  • [x] Hide child comments as well

Confirm

For further actions, you may consider blocking this person and/or reporting abuse

Image 10 Fabian Graßl

Follow

I am a fullstack software developer, IT consultant, and AI engineer. Passionate about clean architecture and practical open-source tools like Spora AI and Markdown Office.

  • Location Erlangen, Germany
  • Joined Oct 29, 2026

Trending on DEV Community

Image 11: Anis Meziani profile image How to cut your AI agent's input tokens: what worked, what failed, and a bench to measure yours #ai#agents#python#llmImage 12: Diogo Soares profile image Black-Box Testing with AI Agents: Test the Rules, Not the Code #ai#testing#softwareengineering#qaImage 13: Apps by Mo profile image How I stopped my Claude Code plan running out midweek #claudecode#productivity#ai#macos

DEV Community — A space to discuss and keep up software development and manage your software career

Built on Forem — the open source software that powers DEV and other inclusive communities.

Made with love and Ruby on Rails. DEV Community © 2016 - 2026.

Image 14: DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log inCreate account

Image 15Image 16Image 17Image 18Image 19

來源:DEV Community · dev.to