Skip to content

Commit 05e79a8

Browse files
committed
wip
1 parent 2d730af commit 05e79a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+731
-1484
lines changed

config/cortex.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,48 @@
326326
],
327327
],
328328

329+
/*
330+
|--------------------------------------------------------------------------
331+
| Agents
332+
|--------------------------------------------------------------------------
333+
|
334+
| Configure agent auto-discovery from your Laravel application.
335+
| All agents must extend the AbstractAgent class.
336+
|
337+
| Agents can be registered in two ways:
338+
|
339+
| 1. Auto-discovery: Automatically discover agents from the configured path
340+
| 2. Manual registration: Use Agent::register() or AgentRegistry::register()
341+
|
342+
| Example manual registration in service provider:
343+
| use Cortex\Facades\Agent;
344+
|
345+
| public function boot(): void
346+
| {
347+
| Agent::register('weather', App\Agents\WeatherAgent::class);
348+
| // Or with an instance:
349+
| Agent::register('custom', new Agent(...));
350+
| }
351+
|
352+
| Usage:
353+
| $agent = Cortex::agent('weather-agent');
354+
| $result = $agent->invoke([], ['location' => 'New York']);
355+
|
356+
*/
357+
'agents' => [
358+
/*
359+
* Enable automatic discovery of agents from the configured path.
360+
*/
361+
'auto_discover' => env('CORTEX_AGENTS_AUTO_DISCOVER', true),
362+
363+
/*
364+
* The directory path where agents are located.
365+
* Defaults to app_path('Agents').
366+
* Agents will be discovered from this directory and its subdirectories.
367+
*/
368+
'path' => env('CORTEX_AGENTS_PATH', null),
369+
],
370+
329371
/*
330372
* Configure the cache settings.
331373
*/

scratchpad.php

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
declare(strict_types=1);
44

55
use Cortex\Cortex;
6+
use Cortex\Agents\Agent;
67
use Cortex\Prompts\Prompt;
78
use Cortex\JsonSchema\SchemaFactory;
9+
use Cortex\Tools\Prebuilt\WeatherTool;
10+
use Cortex\Agents\Prebuilt\WeatherAgent;
811
use Cortex\LLM\Data\Messages\UserMessage;
912
use Cortex\LLM\Data\Messages\SystemMessage;
1013

@@ -81,27 +84,42 @@
8184
new UserMessage('What is the capital of France?'),
8285
]);
8386

84-
// Run an agent with only input parameters
85-
$agent = Cortex::agent('joke_generator')
86-
->prompt('You are a joke generator. You generate jokes about {topic}.')
87-
->llm('ollama:gpt-oss:20b')
88-
->build();
87+
$jokeAgent = new Agent(
88+
name: 'joke_generator',
89+
prompt: 'You are a joke generator. You generate jokes about {topic}.',
90+
llm: 'ollama:gpt-oss:20b',
91+
);
8992

90-
$result = $agent->invoke(input: [
93+
$result = $jokeAgent->invoke(input: [
9194
'topic' => 'programming',
9295
]);
9396

94-
// Run a task
95-
$jokeGenerator = Cortex::task('joke_generator')
96-
->llm('ollama', 'llama3.2')
97-
->user('Tell me a joke about {topic}')
98-
->output(SchemaFactory::object()->properties(
99-
SchemaFactory::string('joke'),
100-
SchemaFactory::string('punchline'),
101-
));
97+
$weatherAgent = WeatherAgent::make()->invoke(input: [
98+
'location' => 'Paris',
99+
]);
102100

103-
$result = $jokeGenerator([
104-
'topic' => 'programming',
101+
Cortex::registerAgent('weather_agent', WeatherAgent::class);
102+
103+
Cortex::agent('weather_agent')->invoke(input: [
104+
'location' => 'Paris',
105+
]);
106+
107+
$agent = Cortex::agent()
108+
->withName('weather_agent')
109+
->withPrompt('You are a weather agent. You tell the weather in {location}.')
110+
->withLLM('ollama:gpt-oss:20b')
111+
->withTools([
112+
WeatherTool::class,
113+
])
114+
->withOutput(SchemaFactory::object()->properties(
115+
SchemaFactory::string('location')->required(),
116+
SchemaFactory::string('summary')->required(),
117+
))
118+
->withMaxSteps(3)
119+
->withStrict(true);
120+
121+
$result = $agent->invoke(input: [
122+
'location' => 'London',
105123
]);
106124

107125
$result = Cortex::embeddings('openai')

src/Agents/AbstractAgent.php

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cortex\Agents;
6+
7+
use Cortex\Contracts\ToolKit;
8+
use Cortex\LLM\Contracts\LLM;
9+
use Cortex\LLM\Data\ChatResult;
10+
use Cortex\LLM\Enums\ToolChoice;
11+
use Cortex\Memory\Contracts\Store;
12+
use Cortex\LLM\Data\ChatStreamResult;
13+
use Cortex\Agents\Contracts\AgentBuilder;
14+
use Cortex\JsonSchema\Types\ObjectSchema;
15+
use Cortex\LLM\Enums\StructuredOutputMode;
16+
17+
abstract class AbstractAgentBuilder implements AgentBuilder
18+
{
19+
public function llm(): LLM|string|null
20+
{
21+
return null;
22+
}
23+
24+
/**
25+
* @return array<int, \Cortex\LLM\Contracts\Tool|\Closure|class-string<\Cortex\LLM\Contracts\Tool>>
26+
*/
27+
public function tools(): array|ToolKit
28+
{
29+
return [];
30+
}
31+
32+
public function toolChoice(): ToolChoice|string
33+
{
34+
return ToolChoice::Auto;
35+
}
36+
37+
public function output(): ObjectSchema|string|null
38+
{
39+
return null;
40+
}
41+
42+
public function outputMode(): StructuredOutputMode
43+
{
44+
return StructuredOutputMode::Auto;
45+
}
46+
47+
public function memoryStore(): ?Store
48+
{
49+
return null;
50+
}
51+
52+
public function maxSteps(): int
53+
{
54+
return 5;
55+
}
56+
57+
public function strict(): bool
58+
{
59+
return true;
60+
}
61+
62+
public function initialPromptVariables(): array
63+
{
64+
return [];
65+
}
66+
67+
public function build(): Agent
68+
{
69+
return new Agent(
70+
name: $this->name(),
71+
prompt: $this->prompt(),
72+
llm: $this->llm(),
73+
tools: $this->tools(),
74+
toolChoice: $this->toolChoice(),
75+
output: $this->output(),
76+
outputMode: $this->outputMode(),
77+
memoryStore: $this->memoryStore(),
78+
initialPromptVariables: $this->initialPromptVariables(),
79+
maxSteps: $this->maxSteps(),
80+
strict: $this->strict(),
81+
);
82+
}
83+
84+
/**
85+
* Convenience method to make an agent instance using the methods defined in this class.
86+
*/
87+
public static function make(array $parameters = []): Agent
88+
{
89+
$builder = app(static::class, $parameters);
90+
91+
return $builder->build();
92+
}
93+
94+
/**
95+
* Convenience method to invoke the built agent instance..
96+
*
97+
* @param array<int, \Cortex\LLM\Contracts\Message> $messages
98+
* @param array<string, mixed> $input
99+
*/
100+
public function invoke(array $messages = [], array $input = []): ChatResult
101+
{
102+
return $this->build()->invoke($messages, $input);
103+
}
104+
105+
/**
106+
* Convenience method to stream from the built agent instance.
107+
*
108+
* @param array<int, \Cortex\LLM\Contracts\Message> $messages
109+
* @param array<string, mixed> $input
110+
*/
111+
public function stream(array $messages = [], array $input = []): ChatStreamResult
112+
{
113+
return $this->build()->stream($messages, $input);
114+
}
115+
}

src/Agents/Agent.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Cortex\Exceptions\PipelineException;
2222
use Cortex\Agents\Stages\HandleToolCalls;
2323
use Cortex\JsonSchema\Types\ObjectSchema;
24+
use Cortex\LLM\Enums\StructuredOutputMode;
2425
use Cortex\LLM\Data\Messages\SystemMessage;
2526
use Illuminate\Contracts\Support\Arrayable;
2627
use Cortex\Agents\Stages\AddMessageToMemory;
@@ -53,6 +54,7 @@ public function __construct(
5354
protected array|ToolKit $tools = [],
5455
protected ToolChoice|string $toolChoice = ToolChoice::Auto,
5556
protected ObjectSchema|string|null $output = null,
57+
protected StructuredOutputMode $outputMode = StructuredOutputMode::Auto,
5658
protected ?Store $memoryStore = null,
5759
protected array $initialPromptVariables = [],
5860
protected int $maxSteps = 5,
@@ -67,6 +69,7 @@ public function __construct(
6769
$this->tools,
6870
$this->toolChoice,
6971
$this->output,
72+
$this->outputMode,
7073
$this->strict,
7174
);
7275
$this->usage = Usage::empty();
@@ -117,7 +120,7 @@ public function invoke(array $messages = [], array $input = []): ChatResult
117120
$this->memory->setMessages($messages);
118121

119122
/** @var \Cortex\LLM\Data\ChatResult $result */
120-
$result = $this->pipeline()->invoke([
123+
$result = $this->pipeline()->disableStreaming()->invoke([
121124
...$input,
122125
'messages' => $this->memory->getMessages(),
123126
]);
@@ -253,10 +256,11 @@ protected static function buildMemory(ChatPromptTemplate $prompt, ?Store $memory
253256
protected static function buildLLM(
254257
ChatPromptTemplate $prompt,
255258
string $name,
256-
?LLMContract $llm = null,
259+
LLMContract|string|null $llm = null,
257260
array $tools = [],
258261
ToolChoice|string $toolChoice = ToolChoice::Auto,
259262
ObjectSchema|string|null $output = null,
263+
StructuredOutputMode $outputMode = StructuredOutputMode::Auto,
260264
bool $strict = true,
261265
): LLMContract {
262266
$llm = $llm !== null
@@ -276,6 +280,7 @@ protected static function buildLLM(
276280
output: $output,
277281
name: $name,
278282
strict: $strict,
283+
outputMode: $outputMode,
279284
);
280285
}
281286

0 commit comments

Comments
 (0)