Skip to main content

API Reference - Technical Details

This reference is aimed at developers who want to extend the plugin or integrate it into their own applications.


๐Ÿ”Œ Plugin Architectureโ€‹

Overviewโ€‹

The plugin is based on the OpenAI Responses API (no longer on Assistants API) and stores all agent configurations locally in Shopware.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Frontend/Backend โ”‚
โ”‚ (Chat Components) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ OpenAIChatService โ”‚
โ”‚ (Main Logic for Conversations) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ–ผ โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Responses โ”‚ โ”‚ Function โ”‚
โ”‚ Service โ”‚ โ”‚ Calling Service โ”‚
โ”‚ (OpenAI API) โ”‚ โ”‚ (Tools) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ OpenAI Responses API โ”‚
โ”‚ (platform.openai.com) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ฆ Database Structureโ€‹

Table: fel_agentsโ€‹

Agent configurations are stored locally.

ColumnTypeDescription
idBINARY(16)Primary key (UUID)
technical_nameVARCHAR(255)Technical name (unique)
display_nameVARCHAR(255)Display name
descriptionLONGTEXTDescription
modelVARCHAR(100)OpenAI model (e.g., gpt-4o-mini)
response_formatVARCHAR(100)auto, json_object, json_schema
agent_configJSONConfiguration (Temperature, etc.)
instructions_systemLONGTEXTSystem Instructions
instructions_initLONGTEXTInit Instructions
instructions_fallbackLONGTEXTFallback Instructions
tool_configJSONEnabled tools
tool_resourcesJSONVector Store IDs, File Bundles
metadataJSONAdditional metadata
is_activeBOOLEANActive?
is_defaultBOOLEANDefault agent?
sales_channel_idBINARY(16)Sales channel (NULL = all)
created_atDATETIMECreation date
updated_atDATETIMELast modified

Example agent_config JSON:

{
"temperature": 0.7,
"top_p": 1.0,
"max_output_tokens": 500,
"reasoning_effort": "medium",
"verbosity": 1.0
}

Example tool_config JSON:

{
"product_search": true,
"get_product_details": true,
"search_logs": true,
"get_order_status": false
}

Table: fel_assistant_logsโ€‹

Knowledge database / FAQ entries.

ColumnTypeDescription
idBINARY(16)Primary key
questionLONGTEXTQuestion
answerLONGTEXTAnswer
contextLONGTEXTAdditional context
meta_infoJSONMetadata (tags, etc.)
sales_channel_idBINARY(16)Sales channel
created_atDATETIMECreation date
updated_atDATETIMELast modified

Example meta_info JSON:

{
"tags": ["shipping", "delivery"],
"source": "manual",
"agent_id": "abc123..."
}

Table: fel_assistant_chat_messageโ€‹

Thread messages (conversation history).

ColumnTypeDescription
idBINARY(16)Primary key
thread_idVARCHAR(255)Thread ID
roleVARCHAR(50)user, assistant, tool
contentLONGTEXTMessage content
tool_callsJSONTool calls (if any)
tool_call_idVARCHAR(255)Tool Call ID
nameVARCHAR(255)Tool name (for role=tool)
token_usageJSONToken statistics
agent_idBINARY(16)Reference to agent
sales_channel_idBINARY(16)Sales channel
created_atDATETIMETimestamp

Example tool_calls JSON:

[
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "product_search",
"arguments": "{\"query\":\"red jacket\",\"limit\":10}"
}
}
]

Example token_usage JSON:

{
"input_tokens": 1500,
"output_tokens": 300,
"cached_tokens": 1200,
"reasoning_tokens": 0,
"total_tokens": 3000
}

Table: fel_assistant_tagsโ€‹

Tag definitions.

ColumnTypeDescription
idBINARY(16)Primary key
nameVARCHAR(255)Tag name (e.g., "shipping")
descriptionTEXTDescription
created_atDATETIMECreation date

Table: fel_assistant_tag_usageโ€‹

Link between logs and tags (Many-to-Many).

ColumnTypeDescription
log_idBINARY(16)Reference to fel_assistant_logs
tag_idBINARY(16)Reference to fel_assistant_tags

๐Ÿ”ง Service Classesโ€‹

OpenAIChatServiceโ€‹

Namespace: FelOAIAssistantsManager\Service\OpenAI\OpenAIChatService

Main Methods:

createThread(array $metadata = []): arrayโ€‹

Creates a new thread (conversation).

Parameters:

  • $metadata (optional): Additional metadata

Returns:

[
'id' => 'thread_abc123',
'object' => 'thread',
'created_at' => 1640000000
]

sendMessage(string $threadId, string $content, ?string $agentId = null): arrayโ€‹

Sends a message to a thread and receives response from agent.

Parameters:

  • $threadId: Thread ID
  • $content: Message content
  • $agentId (optional): Agent ID (if NULL: default agent)

Returns:

[
'role' => 'assistant',
'content' => 'Hello! How can I help?',
'tool_calls' => [...],
'usage' => [
'input_tokens' => 1500,
'output_tokens' => 300,
'cached_tokens' => 1200
]
]

getAgent(string $agentId): ?AgentEntityโ€‹

Loads agent configuration from database.

Parameters:

  • $agentId: Agent ID

Returns:

  • AgentEntity or null

OpenAIResponsesServiceโ€‹

Namespace: FelOAIAssistantsManager\Service\OpenAI\OpenAIResponsesService

Main Methods:

createResponse(array $body): arrayโ€‹

Sends a request to the OpenAI Responses API.

Parameters:

$body = [
'model' => 'gpt-4o-mini',
'messages' => [
['role' => 'user', 'content' => 'Hello']
],
'temperature' => 0.7,
'tools' => [...]
];

Returns:

[
'id' => 'resp_abc123',
'choices' => [
[
'message' => [
'role' => 'assistant',
'content' => 'Hello! How can I help?'
],
'finish_reason' => 'stop'
]
],
'usage' => [
'prompt_tokens' => 1500,
'completion_tokens' => 300,
'total_tokens' => 1800
]
]

FunctionCallingServiceโ€‹

Namespace: FelOAIAssistantsManager\Service\FunctionCalling\FunctionCallingService

Main Methods:

executeFunction(string $functionName, array $arguments, Context $context): arrayโ€‹

Executes a tool function.

Parameters:

  • $functionName: Tool name (e.g., product_search)
  • $arguments: Arguments as array
  • $context: Shopware Context

Returns:

[
'success' => true,
'data' => [...],
'error' => null
]

getToolDefinitions(array $enabledTools): arrayโ€‹

Generates tool definitions for OpenAI.

Parameters:

  • $enabledTools: Array with enabled tool names

Returns:

[
[
'type' => 'function',
'function' => [
'name' => 'product_search',
'description' => 'Searches for products...',
'parameters' => [
'type' => 'object',
'properties' => [
'query' => [
'type' => 'string',
'description' => 'Search term'
],
'limit' => [
'type' => 'integer',
'description' => 'Max. number'
]
],
'required' => ['query']
]
]
]
]

๐ŸŒ REST API Endpointsโ€‹

Agent Managementโ€‹

POST /api/fel-oai/agentโ€‹

Creates a new agent.

Request Body:

{
"technicalName": "my_agent",
"displayName": "My Agent",
"model": "gpt-4o-mini",
"instructionsSystem": "You are a helpful assistant",
"agentConfig": {
"temperature": 0.7,
"max_output_tokens": 500
},
"toolConfig": {
"product_search": true,
"search_logs": true
}
}

Response:

{
"success": true,
"data": {
"id": "abc123...",
"technicalName": "my_agent",
...
}
}

PATCH /api/fel-oai/agent/{agentId}โ€‹

Updates an agent.

Request Body:

{
"displayName": "New Name",
"agentConfig": {
"temperature": 0.5
}
}

DELETE /api/fel-oai/agent/{agentId}โ€‹

Deletes an agent.

Response:

{
"success": true
}

Chat Interactionโ€‹

POST /api/fel-oai/chat/threadโ€‹

Creates a new thread.

Request Body:

{
"metadata": {
"user_id": "user123",
"source": "storefront"
}
}

Response:

{
"threadId": "thread_abc123"
}

POST /api/fel-oai/chat/messageโ€‹

Sends a message.

Request Body:

{
"threadId": "thread_abc123",
"content": "I'm looking for a jacket",
"agentId": "agent_xyz"
}

Response:

{
"role": "assistant",
"content": "I'd be happy to help! What color?",
"toolCalls": [],
"usage": {
"inputTokens": 1500,
"outputTokens": 120,
"cachedTokens": 800
}
}

Log Managementโ€‹

GET /api/fel-oai/logsโ€‹

Retrieves logs.

Query Parameters:

  • limit (optional): Max. number (default: 50)
  • offset (optional): Offset for pagination
  • fromDate (optional): From date (ISO 8601)
  • toDate (optional): To date
  • agentId (optional): Filter by agent
  • tags (optional): Filter by tags (comma-separated)

Response:

{
"data": [
{
"id": "log123",
"question": "How long does shipping take?",
"answer": "2-3 business days",
"createdAt": "2025-12-29T10:30:00Z",
"tags": ["shipping"]
}
],
"total": 150
}

POST /api/fel-oai/logsโ€‹

Creates log entry (FAQ).

Request Body:

{
"question": "Can I pay by invoice?",
"answer": "Yes, from $50 minimum order value",
"context": "Payment methods invoice",
"tags": ["payment", "invoice"]
}

๐Ÿ”จ Eventsโ€‹

The plugin dispatches various events that you can use for your own extensions.

ResponseCreatedEventโ€‹

Triggered: After every successful OpenAI Response

Event Class: FelOAIAssistantsManager\Event\ResponseCreatedEvent

Available Data:

$event->getResponse();   // OpenAI Response
$event->getRequest(); // Original Request Body
$event->getAgentId(); // Agent ID
$event->getThreadId(); // Thread ID

Example Subscriber:

use FelOAIAssistantsManager\Event\ResponseCreatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyCustomSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ResponseCreatedEvent::NAME => 'onResponseCreated'
];
}

public function onResponseCreated(ResponseCreatedEvent $event): void
{
$response = $event->getResponse();
// Your logic here (e.g., Analytics, Logging)
}
}

ToolExecutedEventโ€‹

Triggered: After every tool execution

Event Class: FelOAIAssistantsManager\Event\ToolExecutedEvent

Available Data:

$event->getToolName();      // Tool name
$event->getArguments(); // Passed arguments
$event->getResult(); // Tool result
$event->getExecutionTime(); // Execution time in ms

ThreadCreatedEventโ€‹

Triggered: When creating a new thread

Event Class: FelOAIAssistantsManager\Event\ThreadCreatedEvent

Available Data:

$event->getThreadId();
$event->getMetadata();
$event->getSalesChannelId();

๐Ÿ› ๏ธ Adding Custom Toolsโ€‹

You can add your own tools (functions).

Step 1: Tool Definitionโ€‹

Create a class in src/Service/FunctionCalling/Functions/:

namespace FelOAIAssistantsManager\Service\FunctionCalling\Functions;

use Shopware\Core\Framework\Context;

class MyCustomTool implements FunctionInterface
{
public function getName(): string
{
return 'my_custom_tool';
}

public function getDescription(): string
{
return 'Description of what the tool does';
}

public function getParameters(): array
{
return [
'type' => 'object',
'properties' => [
'param1' => [
'type' => 'string',
'description' => 'First parameter'
],
'param2' => [
'type' => 'integer',
'description' => 'Second parameter'
]
],
'required' => ['param1']
];
}

public function execute(array $arguments, Context $context): array
{
$param1 = $arguments['param1'] ?? null;
$param2 = $arguments['param2'] ?? 10;

// Your logic here
$result = $this->doSomething($param1, $param2);

return [
'success' => true,
'data' => $result
];
}

private function doSomething(string $param1, int $param2): mixed
{
// Implementation
return ['result' => 'something'];
}
}

Step 2: Register Toolโ€‹

In src/Resources/config/services.xml:

<service id="FelOAIAssistantsManager\Service\FunctionCalling\Functions\MyCustomTool">
<tag name="fel_oai.function"/>
</service>

Step 3: Activate Tool in Agentโ€‹

The tool is now available in the agent configuration and can be activated.


๐Ÿ“Š Configuration (config.xml)โ€‹

OpenAI API Keyโ€‹

<input-field type="password">
<name>apiKey</name>
<label>OpenAI API Key</label>
<helpText>Your secret API key from platform.openai.com</helpText>
</input-field>

Access in Code:

$apiKey = $this->systemConfigService->get('FelOAIAssistantsManager.config.apiKey');

Logging Optionsโ€‹

<input-field type="bool">
<name>enableThreadLogging</name>
<label>Enable Thread Logging</label>
<defaultValue>true</defaultValue>
</input-field>

<input-field type="bool">
<name>enableUsageCounter</name>
<label>Track Token Usage</label>
<defaultValue>true</defaultValue>
</input-field>

๐Ÿ” Securityโ€‹

API Key Protectionโ€‹

The API key is stored encrypted in the database:

  • Type: password (not in plain text)
  • Access only via backend/API with admin rights

Rate Limitingโ€‹

Recommendation: Implement your own rate limiting for public endpoints:

use Symfony\Component\RateLimiter\RateLimiterFactory;

class ChatController
{
public function __construct(
private RateLimiterFactory $chatLimiter
) {}

public function sendMessage(Request $request): JsonResponse
{
$limiter = $this->chatLimiter->create($request->getClientIp());

if (!$limiter->consume(1)->isAccepted()) {
throw new TooManyRequestsHttpException();
}

// Normal processing...
}
}

CORSโ€‹

For frontend integrations you need to configure CORS:

# config/packages/nelmio_cors.yaml
nelmio_cors:
paths:
'^/api/fel-oai':
allow_origin: ['https://your-domain.com']
allow_methods: ['GET', 'POST', 'PATCH', 'DELETE']
allow_headers: ['Content-Type', 'Authorization']

๐Ÿงช Testingโ€‹

Unit Testsโ€‹

use PHPUnit\Framework\TestCase;
use FelOAIAssistantsManager\Service\OpenAI\OpenAIChatService;

class OpenAIChatServiceTest extends TestCase
{
public function testCreateThread(): void
{
$service = $this->createMock(OpenAIChatService::class);
$service->method('createThread')
->willReturn(['id' => 'thread_123']);

$result = $service->createThread();

$this->assertArrayHasKey('id', $result);
$this->assertStringStartsWith('thread_', $result['id']);
}
}

Integration Testsโ€‹

use Shopware\Core\Test\TestDefaults;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class ChatIntegrationTest extends KernelTestCase
{
public function testSendMessage(): void
{
$chatService = $this->getContainer()->get(OpenAIChatService::class);

$thread = $chatService->createThread();
$response = $chatService->sendMessage(
$thread['id'],
'Hello',
'agent_test_id'
);

$this->assertArrayHasKey('content', $response);
$this->assertNotEmpty($response['content']);
}
}

๐Ÿ“š Additional Resourcesโ€‹

OpenAI Documentationโ€‹

Shopware Documentationโ€‹


๐Ÿ”„ Migration from v1.x to v2.xโ€‹

Most Important Changesโ€‹

v1.x (Assistants API)v2.x (Responses API)
Assistants stored on OpenAIAgents locally in Shopware
assistant_idagent_id
OpenAI ThreadsLocal thread management
RunServiceResponsesService
Tools via Assistant APITools via Function Calling

Perform Migrationโ€‹

  1. Back up data:

    mysqldump shopware fel_assistant_* > backup.sql
  2. Update plugin:

    composer require fel/oai-assistants-manager:^2.0
    bin/console plugin:update FelOAIAssistantsManager
  3. Migrate agents:

    • Export old Assistants from OpenAI (manually)
    • Create new Agents in Shopware
    • Transfer instructions and tools
  4. Adjust API calls:

    // Old (v1.x)
    $assistant = $service->getAssistant($assistantId);

    // New (v2.x)
    $agent = $service->getAgent($agentId);

๐Ÿ“ž Support for Developersโ€‹

Technical Support:

Documentation:


Next Stepsโ€‹

You now have access to all technical details!

โžก๏ธ Glossary - Look up terms

โžก๏ธ Troubleshooting - Solve problems

โžก๏ธ Back to Main Documentation