Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,42 @@ cd wp-agents && composer install
wp plugin activate wp-agents
```

## REST API

Each agent can be accessed programmatically through the WordPress REST API.

This allows external systems or front-end applications to send a message to any registered agent and receive the model’s response in JSON format.

**Endpoint**

```bash
POST /wp-json/wp-agents/v1/chat
```

**Example**

```bash
curl --location 'https://example.com/wp-json/wp-agents/v1/chat' \
--header 'Content-Type: application/json' \
--data '{
"agent": "taxonomy_agent",
"message": "Hello"
}'
```

**Example response**

```json
{
"agent": "taxonomy_agent",
"message": "Hello",
"response": {
"role": "assistant",
"content": "Hello! How can I assist you today?"
}
}
```

## Demo

https://github.com/santerref/wp-agents-demo
Expand Down
7 changes: 0 additions & 7 deletions inc/inputs.php

This file was deleted.

15 changes: 7 additions & 8 deletions lib/agents/class-abstract-llm-agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Wp_Agents\Agents;

use Wp_Agents\Providers\Provider_Interface;
use Wp_Agents\Services\Provider_Manager;
use Wp_Agents\System\Agent_Runner;

abstract class Abstract_Llm_Agent {

Expand All @@ -12,24 +14,21 @@ abstract class Abstract_Llm_Agent {

protected bool $json = false;

protected array $actions = array();

protected array $filters = array();

protected array $tools = array();

abstract public function instructions(): string;

public function actions(): array {
return $this->actions;
}

public function filters(): array {
return $this->filters;
}

public function run( mixed $input, Provider_Interface $provider ): mixed {
return $provider->complete( $input, $this );
public function prompt( mixed $input ): Agent_Runner {
return new Agent_Runner(
$input,
$this
);
}

public function get_model(): string {
Expand Down
7 changes: 7 additions & 0 deletions lib/exceptions/class-agent-not-found-exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Wp_Agents\Exceptions;

class Agent_Not_Found_Exception extends \Exception {

}
7 changes: 0 additions & 7 deletions lib/exceptions/class-input-not-registered-exception.php

This file was deleted.

7 changes: 0 additions & 7 deletions lib/exceptions/class-skip-agent-exception.php

This file was deleted.

20 changes: 0 additions & 20 deletions lib/inputs/class-abstract-input.php

This file was deleted.

32 changes: 0 additions & 32 deletions lib/inputs/class-post-updated-input.php

This file was deleted.

54 changes: 35 additions & 19 deletions lib/providers/class-open-ai-provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Wp_Agents\Providers;

use Wp_Agents\Agents\Abstract_Llm_Agent;
use Wp_Agents\System\Message;
use Wp_Agents\System\Message_Stack;
use Wp_Agents\Tools\Tool_Registry;

class Open_Ai_Provider implements Provider_Interface {
Expand All @@ -13,23 +15,20 @@ public function __construct( string $api_key ) {
$this->api_key = $api_key;
}

public function complete( string $prompt, Abstract_Llm_Agent $agent ): string {
public function chat( string $input, Abstract_Llm_Agent $agent ): Message_Stack {
$client = \OpenAI::client( $this->api_key );
$tools = $agent->tools();

$messages = array(
$messages = new Message_Stack(
array(
'role' => 'system',
'content' => $agent->instructions(),
),
array(
'role' => 'user',
'content' => $prompt,
),
new Message( 'system', $agent->instructions() ),
new Message( 'user', $input ),
)
);

$parameters = array(
'model' => $agent->get_model(),
'messages' => $messages,
'messages' => $messages->to_raw_array(),
'response_format' => array( 'type' => $agent->json() ? 'json_object' : 'text' ),
);

Expand All @@ -40,8 +39,14 @@ public function complete( string $prompt, Abstract_Llm_Agent $agent ): string {

$response = $client->chat()->create( $parameters );

$message = $response->choices[0]->message;
$messages[] = $message->toArray();
$message = $response->choices[0]->message;
$messages->add(
new Message(
$message->role,
$message->content,
$message->toArray()
)
);

// phpcs:ignore WordPress.NamingConventions.ValidVariableName
if ( ! empty( $message->toolCalls ) ) {
Expand All @@ -55,24 +60,35 @@ public function complete( string $prompt, Abstract_Llm_Agent $agent ): string {
}
$result = $tool_registry->execute( $function->name, $args );

$messages[] = array(
'role' => 'tool',
'tool_call_id' => $call->id,
'content' => wp_json_encode( $result ),
$messages->add(
new Message(
'tool',
wp_json_encode( $result ),
array(
'tool_call_id' => $call->id,
)
)
);
}

$follow = $client->chat()->create(
array(
'model' => $agent->get_model(),
'messages' => $messages,
'messages' => $messages->to_raw_array(),
'response_format' => array( 'type' => $agent->json() ? 'json_object' : 'text' ),
)
);

return $follow->choices[0]->message->content ?? '';
$message = $follow->choices[0]->message;
$messages->add(
new Message(
$message->role,
$message->content,
$message->toArray(),
)
);
}

return $response->choices[0]->message->content ?? '';
return $messages;
}
}
3 changes: 2 additions & 1 deletion lib/providers/class-provider-interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace Wp_Agents\Providers;

use Wp_Agents\Agents\Abstract_Llm_Agent;
use Wp_Agents\System\Message_Stack;

interface Provider_Interface {

public function complete( string $prompt, Abstract_Llm_Agent $agent ): string;
public function chat( string $input, Abstract_Llm_Agent $agent ): Message_Stack;
}
38 changes: 9 additions & 29 deletions lib/services/class-agent-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,22 @@
namespace Wp_Agents\Services;

use Wp_Agents\Agents\Abstract_Llm_Agent;
use Wp_Agents\Exceptions\Skip_Agent_Exception;
use Wp_Agents\Exceptions\Agent_Not_Found_Exception;

class Agent_Manager {

protected static array $agents = array();

public static function register( string $name, Abstract_Llm_Agent $agent ): void {
self::$agents[ $name ] = $agent;

foreach ( $agent->actions() as $action ) {
$input = Input_Manager::make( $action );

add_action(
$action,
function ( ...$args ) use ( $agent, $input, $name, $action ) {
Recursion_Guard::run(
"{$name}:{$action}",
function () use ( $input, $args, $agent ) {
try {
$built_input = $input->build( ...$args );
if ( ! empty( $built_input ) ) {
$provider = Provider_Manager::get( $agent->get_provider() );
$answer = $agent->run( $built_input, $provider );
$agent->handle_response( $answer, $args );
}
} catch ( Skip_Agent_Exception $e ) {
wp_agents_logger()->error( $e->getMessage() );
}
}
);
},
$input->get_priority(),
$input->get_accepted_args()
);
public static function register( string $name, string $agent_class ): void {
self::$agents[ $name ] = new $agent_class();
}

public static function get( string $name ): Abstract_Llm_Agent {
if ( ! isset( self::$agents[ $name ] ) ) {
throw new Agent_Not_Found_Exception();
}

return self::$agents[ $name ];
}

public static function boot(): void {
Expand Down
27 changes: 0 additions & 27 deletions lib/services/class-input-manager.php

This file was deleted.

28 changes: 28 additions & 0 deletions lib/system/class-agent-runner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Wp_Agents\System;

use Wp_Agents\Agents\Abstract_Llm_Agent;
use Wp_Agents\Providers\Provider_Interface;
use Wp_Agents\Services\Provider_Manager;

class Agent_Runner {

protected string $input;

protected Provider_Interface $provider;

protected Abstract_Llm_Agent $agent;

public function __construct( string $input, Abstract_Llm_Agent $agent ) {
$this->input = $input;
$this->agent = $agent;
$this->provider = Provider_Manager::get( $agent->get_provider() );
}

public function chat(): Message {
$message_stack = $this->provider->chat( $this->input, $this->agent );

return $message_stack->last();
}
}
Loading