PHPackages                             hiddenhatpress/openai-assistants - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. hiddenhatpress/openai-assistants

ActiveLibrary[API Development](/categories/api)

hiddenhatpress/openai-assistants
================================

A quick and dirty client for OpenAI's assistants API

v1.0.7(2y ago)122.7k1[1 issues](https://github.com/hiddenhatpress/openai-assistants/issues)Apache-2.0PHPPHP ^8.1

Since Nov 24Pushed 2y ago1 watchersCompare

[ Source](https://github.com/hiddenhatpress/openai-assistants)[ Packagist](https://packagist.org/packages/hiddenhatpress/openai-assistants)[ Docs](https://github.com/hiddenhatpress/openai-assistants)[ RSS](/packages/hiddenhatpress-openai-assistants/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (3)Versions (9)Used By (0)

openai-assistants
=================

[](#openai-assistants)

A quick and dirty client for OpenAI's assistants API.

NOTE
----

[](#note)

Although this package is still maintained for now (I'm using it in [Shelley](https://github.com/getinstancemz/shelley)), the Assistants API is now included in the full OpenAI Client at [orhanerday/open-ai](https://github.com/orhanerday/open-ai). You might want to use that for a much wider feature set. This library plugged a gap that has now been filled. That said, read on for a worked example of file retrieval with the OpenAI Assistants API.

OpenAI API docs
---------------

[](#openai-api-docs)

- [OpenAI Assistants overview](https://platform.openai.com/docs/assistants/overview)
- [OpenAI API documentation](https://platform.openai.com/docs/api-reference/assistants)

Installation
------------

[](#installation)

The easiest way to get this code is via Composer:

```
composer require hiddenhatpress/openai-assistants

```

Overview
--------

[](#overview)

```
use hiddenhatpress\openai\assistants\Assistants;
use hiddenhatpress\openai\assistants\AsstComms;

$token = getenv('OPENAI_API_KEY');
// this model needed for retrieval tools
$model = "gpt-4-1106-preview";

$asstcomms = new AsstComms($model, $token);
$assistants = new Assistants($asstcomms);
```

The `Assistants` class is really only a factory for objects which provide thin client access to the [assistant](https://platform.openai.com/docs/api-reference/assistants), [thread](https://platform.openai.com/docs/api-reference/threads). [messages](https://platform.openai.com/docs/api-reference/messages) and [runs](https://platform.openai.com/docs/api-reference/runs) APIs.

```
$asstservice = $assistants->getAssistantService();
$fileservice  = $assistants->getAssistantFileService();
$threadservice = $assistants->getThreadService();
$runservice = $assistants->getRunService();
$messageservice = $assistants->getMessageService();
```

Quick start
-----------

[](#quick-start)

The basic workflow for the Assistants API is:

1. Create an assistant
2. Optionally add files to the assistant
3. Create a thread (so that different users can use the assistant through your interface)
4. Create a message representing a user's query and add it to thread
5. Run the thread
6. Poll the status of the the run until its status is `completed`
7. Get the latest message (the system's response) from the thread and return to the user
8. Repeat from step 4 as needed

We're going to create an assistant to help us read the [letters of Pliny the Younger](https://www.gutenberg.org/ebooks/2811).

### Access assistants

[](#access-assistants)

First, let's check that we haven't already created an assistant named `pliny-assistant`:

```
// will get 20 by default
$entities = $asstservice->list();
$assistantid = null;
$name = "pliny-assistant";

foreach ($entities['data'] as $asst) {
    if ($asst['name'] == $name) {
        $assistantid = $asst['id'];
    }
}
```

> **NOTE** because the list endpoint returns 20 elements by default, this approach would not scale if you had more than 20 asssistants. In a robust system you'd likely have stored an assistant id. If you wanted to create a reliable version of this dynamic name-based logic you'd need to page through the data. `list()` supports `limit` -- up to 100 -- as well as `before` and `after` fields.

### Create an assistant and upload a file

[](#create-an-assistant-and-upload-a-file)

For a first run, we'll need to actually create the assistant and upload a source file (the [text version](https://www.gutenberg.org/ebooks/2811.txt.utf-8) of Pliny's letters saved as `pliny.txt`).

```
if (empty($assistantid)) {
    // create the assistant
    $asstresp = $asstservice->create(
         $name,
         "You are an ancient history assistant specialising in Pliny the Younger",
         ["retrieval"]
    );
    $assistantid = $asstresp['id'];

    // upload file
    $fileresp = $fileservice->createAndAssignAssistantFile($assistantid, "pliny.txt" );
}
```

The arguments to `create()` are a name, a set of instructions, and a list of tool types. These can be `code_interpreter`, `retrieval`, or `function`. We are creating a retrieval assistant -- that is, an assistant specialised in working with texts we provide. We're giving it a historical text -- but the assistant would likely come into its own interpreting files that the model has not already been trained on -- a novel-in-progress perhaps, or corporate documents.

The `AssistantFile` class accesses the file aspect of the [assistants API](https://platform.openai.com/docs/api-reference/assistants) and the [File API](https://platform.openai.com/docs/api-reference/files). So `createAndAssignAssistantFile()` uploads a given file and then associates it with an assistant.

Now we have an assistant with access to the text we are interested in. Let's try asking it a question.

### Setting up a message for running

[](#setting-up-a-message-for-running)

In order to send a message we need to create a thread and add a message to it.

```
// create a thread
$threadresp = $threadservice->create();
$threadid = $threadresp['id'];

// create a message and add to the thread
$content = "Discuss the ways that Pliny talks about fish in his letters.";
$msgresp = $messageservice->create($threadid, $content);
```

### Running the thread to send the message

[](#running-the-thread-to-send-the-message)

Next, we need to tell the API to run the thread. We use the [runs API](https://platform.openai.com/docs/api-reference/runs) for this.

```
$runresp = $runservice->create($threadid, $assistantid);
while($runresp['status'] != "completed") {
    sleep(1);
    print "# polling {$runresp['status']}\n";
    $runresp = $runservice->retrieve($threadid, $runresp['id']);
}
```

Because the service does not block, we need to poll it until it the run status is `completed`.

### Accessing the latest message from the thread

[](#accessing-the-latest-message-from-the-thread)

We can list the messages using the [messages API](https://platform.openai.com/docs/api-reference/messages).

```
// access the response
$msgs = $messageservice->listMessages($threadid);
print $msgs['data'][0]['content'][0]['text']['value'];
print "\n";
```

By default, messages are returned in descending order, so the first element will be the latest.

### Some output

[](#some-output)

Let's run the code and get some ancient fish news.

```
# polling queued
# polling in_progress
# polling in_progress
...

```

> Pliny the Younger mentioned fish in the context of his letters to highlight certain aspects or qualities of his environment or surroundings:
>
> 1. He discusses the offerings of his local sea and expresses a somewhat limited pride in its bounty. He says, "I cannot boast that our sea is plentiful in choice fish" but then goes on to recognize that it does provide for "capital soles and prawns." This indicates a modest abundance of certain kinds of fish, and he contrasts this with the abundant provisions of other types, such as milk, which he proudly notes his villa's ability to excel in even when compared to inland places【7†source】.
>
> ...

### Tidying up: unassign and delete assistant files

[](#tidying-up-unassign-and-delete-assistant-files)

In real world code, we would not usually build an assistant only to tear it down again at the end of our process. We'd be more likely to establish an assistant and use it over time, creating new threads for new users. These threads might also persist for some time.

Here, however, we want to leave things as we found them. First, let's delete the file we uploaded.

We can get an assistant's file ids from the [assistants API](https://platform.openai.com/docs/api-reference/assistants). In this example, we have access to this data already, but let's assume we only have an assistant id to hand.

```
// get the files from the assistant
$files = $fileservice->listAssistantFiles($assistantid);
foreach ($files['data'] as $finfo) {
    // unassign and delete
    $fileservice->unassignAndDeleteAssistantFile($assistantid, $finfo['id']);
}
```

`AssistantFiles::listAssistantFiles()` gives us an array of associated files. We can use the `id` field of each with `unassignAndDeleteAssistantFile()` to remove the association between assistant and file and then delete the file from the repository.

### Tidying up: delete the assistant

[](#tidying-up-delete-the-assistant)

Finally, we delete the assistant altogether.

```
// delete the assistant
$del = $asstservice->del($assistantid);
```

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~21 days

Recently: every ~36 days

Total

8

Last Release

751d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/071ae869092d63a717883f9bca4e8d71e9c52f818a2e9000ee82cd889bcc73fd?d=identicon)[mattz](/maintainers/mattz)

---

Top Contributors

[![poppbook](https://avatars.githubusercontent.com/u/20628006?v=4)](https://github.com/poppbook "poppbook (19 commits)")[![getinstancemz](https://avatars.githubusercontent.com/u/1153113?v=4)](https://github.com/getinstancemz "getinstancemz (3 commits)")

---

Tags

ai

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/hiddenhatpress-openai-assistants/health.svg)

```
[![Health](https://phpackages.com/badges/hiddenhatpress-openai-assistants/health.svg)](https://phpackages.com/packages/hiddenhatpress-openai-assistants)
```

###  Alternatives

[wordpress/mcp-adapter

Adapter for Abilities API, letting WordPress abilities to be used as MCP tools, resources or prompts

74855.8k1](/packages/wordpress-mcp-adapter)[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

47073.9k5](/packages/deepseek-php-deepseek-php-client)[gemini-api-php/client

API client for Google's Gemini API

216221.4k5](/packages/gemini-api-php-client)[chriskonnertz/deeply

DeepLy is a PHP client for the DeepL.com translation API

230116.2k8](/packages/chriskonnertz-deeply)[moe-mizrak/laravel-openrouter

Laravel package for OpenRouter (A unified interface for LLMs)

153107.2k2](/packages/moe-mizrak-laravel-openrouter)[wordpress/php-ai-client

A provider agnostic PHP AI client SDK to communicate with any generative AI models of various capabilities using a uniform API.

26236.6k14](/packages/wordpress-php-ai-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
