> ## Documentation Index
> Fetch the complete documentation index at: https://phaseo.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Phaseo Gateway base URL: https://api.phaseo.app/v1. Send `Authorization: Bearer $PHASEO_API_KEY` with every request.
> Model IDs look like `provider/model`, for example `openai/gpt-6-astra`. Do not guess IDs: list them with `GET /v1/models` or check https://phaseo.app/models. `phaseo/free` routes to an available free model and needs no wallet balance.
> For new text integrations prefer `POST /v1/responses`. `POST /v1/chat/completions` (OpenAI format) and `POST /v1/messages` (Anthropic format) suit existing code.
> The full API contract is https://phaseo.app/docs/openapi/v1/openapi.yaml. Official SDKs: `@phaseo/sdk` (TypeScript) and `phaseo` (Python), plus Go, C#, PHP, Ruby and Rust.
> Search these docs over MCP at https://phaseo.app/docs/mcp, and install Phaseo skills with `npx skills add https://phaseo.app/docs`. If a page is wrong or out of date, report it with the MCP `submit_feedback` tool.
> Manage Phaseo accounts with the `phaseo` CLI (`npm install -g @phaseo/cli`, then `phaseo login` or `phaseo login --device-code`), the `/v1` Management API or the MCP server at `https://mcp.phaseo.app/mcp?access=manage`. Do not send users to the dashboard for account tasks. A person is still needed for sign-up, approving a sign-in, paying the first top-up on the checkout link that `phaseo credits add` returns when no card is saved, confirming each saved-card top-up from the emailed link, and account security (password, MFA, passkeys). Create API keys with `phaseo keys create --name <name> --json`; never guess one. Credit top-ups need `phaseo login --scopes billing:write` first. Task map: https://phaseo.app/docs/v1/developers/manage-from-an-agent.md.

# استخدام Agent SDK

> ابنِ أول وكيل يستخدم الأدوات باستخدام Agent SDK من Phaseo، وتتبّع طريقة عمل التشغيل.

عرّف أداة، وأنشئ وكيلًا، وشغّله باستخدام عميل Gateway. يستدعي النموذج أداتك، فتنفّذها الحزمة وتعيد النتيجة إليه، ويعود التشغيل عندما يجيب النموذج دون استدعاء أداة، أو يتوقف بانتظار شخص، أو يتحقق [شرط إيقاف](https://phaseo.app/docs/ar/v1/sdk-reference/agent/stop-conditions.md). وإذا بلغ التشغيل حد الخطوات أولًا، تطلق الحزمة خطأً؛ ولا تعيد التشغيل بالحالة `stopped` سوى Rust. لا تستضيف Phaseo الوكيل ولا تخزّن عمليات تشغيله؛ بل يفعل ذلك تطبيقك.

## ابنِ أول وكيل

```typescript TypeScript theme={null}
import {
  createAgent,
  createGatewayAgentClient,
  defineTool,
} from "@phaseo/agent-sdk";

const lookupDocs = defineTool({
  id: "lookup-docs",
  description: "Look up an internal docs page by slug.",
  parameters: {
    type: "object",
    properties: {
      slug: { type: "string" },
    },
    required: ["slug"],
    additionalProperties: false,
  },
  async execute(input: { slug: string }) {
    return {
      slug: input.slug,
      url: `https://phaseo.app/docs/v1/${input.slug}`,
    };
  },
});

const agent = createAgent({
  id: "support-docs-agent",
  model: "openai/gpt-6-astra",
  instructions: "Use tools when helpful and finish with a concise answer.",
  tools: [lookupDocs],
});

const result = await agent.run({
  input: "Find the docs page for presets and explain when to use them.",
  client: createGatewayAgentClient({
    clientOptions: {
      apiKey: process.env.PHASEO_API_KEY!,
    },
  }),
});

console.log(result.output);
```

```python Python theme={null}
import os
from phaseo_agent import AgentTool, create_agent, create_gateway_agent_client, define_tool

lookup_docs = define_tool(AgentTool(
    id="lookup-docs",
    description="Look up an internal docs page by slug.",
    parameters={
        "type": "object",
        "properties": {"slug": {"type": "string"}},
        "required": ["slug"],
        "additionalProperties": False,
    },
    execute=lambda tool_input, runtime: {
        "slug": tool_input["slug"],
        "url": f"https://phaseo.app/docs/v1/{tool_input['slug']}",
    },
))

agent = create_agent({
    "id": "support-docs-agent",
    "model": "openai/gpt-6-astra",
    "instructions": "Use tools when helpful and finish with a concise answer.",
    "tools": [lookup_docs],
})

result = agent.run(
    input="Find the docs page for presets and explain when to use them.",
    client=create_gateway_agent_client(client_options={"api_key": os.environ["PHASEO_API_KEY"]}),
)

print(result.output)
```

```go Go theme={null}
package main

import (
  "context"
  "fmt"

  phaseoagent "github.com/phaseoteam/Phaseo/packages/sdk/agent-sdk-go"
)

func main() {
  client, err := phaseoagent.CreateGatewayAgentClient(phaseoagent.GatewayAgentClientOptions{})
  if err != nil {
    panic(err) // PHASEO_API_KEY is required
  }

  lookup := phaseoagent.DefineTool(phaseoagent.Tool{
    ID:          "lookup_docs",
    Description: "Look up a Phaseo documentation topic",
    Parameters: map[string]any{
      "type":       "object",
      "properties": map[string]any{"topic": map[string]any{"type": "string"}},
      "required":   []string{"topic"},
    },
    Execute: func(input any, runtime phaseoagent.RuntimeContext) (any, error) {
      args, _ := input.(map[string]any)
      return map[string]any{"topic": args["topic"], "found": true}, nil
    },
  })

  agent := phaseoagent.CreateAgent(phaseoagent.AgentDefinition{
    ID:           "docs-agent",
    Model:        "openai/gpt-6-astra",
    Instructions: "Use tools when helpful and finish with a concise answer.",
    Tools:        []phaseoagent.Tool{lookup},
    MaxSteps:     6,
  })

  result, err := agent.Run(context.Background(), phaseoagent.RunOptions{
    Input:  "Explain when to use routing presets.",
    Client: client,
  })
  if err != nil {
    panic(err)
  }

  fmt.Println(result.Output)
  fmt.Println(result.Run.Status, result.Usage.TotalTokens)
}
```

```csharp C# theme={null}
using System.Text.Json;
using PhaseoAgentSdk;

var lookup = AgentSdk.DefineTool(new Tool(
    "lookup_docs",
    async (input, runtime) =>
    {
        var topic = ((JsonElement)input!).GetProperty("topic").GetString();
        return new { topic, found = true };
    },
    "Look up a Phaseo documentation topic",
    new Dictionary<string, object?>
    {
        ["type"] = "object",
        ["properties"] = new Dictionary<string, object?> { ["topic"] = new { type = "string" } },
        ["required"] = new[] { "topic" },
    }));

var agent = AgentSdk.CreateAgent(new AgentDefinition
{
    Id = "docs-agent",
    Model = "openai/gpt-6-astra",
    Instructions = "Use tools when helpful and finish with a concise answer.",
    Tools = new[] { lookup },
    MaxSteps = 6,
});

var result = await agent.Run(new RunOptions
{
    Input = "Explain when to use routing presets.",
    Client = AgentSdk.CreateGatewayAgentClient(), // throws if PHASEO_API_KEY is missing
});

Console.WriteLine(result.Output);
Console.WriteLine($"{result.Run.Status} {result.Usage.TotalTokens}");
```

```php PHP theme={null}
<?php
require "vendor/autoload.php";

use Phaseo\AgentSdk\AgentDefinition;
use Phaseo\AgentSdk\AgentSdk;
use Phaseo\AgentSdk\Tool;

$lookup = AgentSdk::defineTool(new Tool(
    id: "lookup_docs",
    execute: fn (array $input, $runtime) => ["topic" => $input["topic"], "found" => true],
    description: "Look up a Phaseo documentation topic",
    parameters: [
        "type" => "object",
        "properties" => ["topic" => ["type" => "string"]],
        "required" => ["topic"],
    ],
));

$agent = AgentSdk::createAgent(new AgentDefinition(
    id: "docs-agent",
    model: "openai/gpt-6-astra",
    instructions: "Use tools when helpful and finish with a concise answer.",
    tools: [$lookup],
    maxSteps: 6,
));

$result = $agent->run(
    input: "Explain when to use routing presets.",
    client: AgentSdk::createGatewayAgentClient() // throws if PHASEO_API_KEY is missing
);

echo $result->output . PHP_EOL;
echo $result->run->status . " " . $result->usage["total_tokens"] . PHP_EOL;
```

```ruby Ruby theme={null}
require "phaseo_agent_sdk"

lookup = PhaseoAgentSdk.define_tool(
  PhaseoAgentSdk::Tool.new(
    id: "lookup_docs",
    description: "Look up a Phaseo documentation topic",
    parameters: {
      type: "object",
      properties: { topic: { type: "string" } },
      required: ["topic"]
    },
    execute: ->(input, runtime) { { topic: input["topic"], found: true } }
  )
)

agent = PhaseoAgentSdk.create_agent(
  id: "docs-agent",
  model: "openai/gpt-6-astra",
  instructions: "Use tools when helpful and finish with a concise answer.",
  tools: [lookup],
  max_steps: 6
)

result = agent.run(
  input: "Explain when to use routing presets.",
  client: PhaseoAgentSdk.create_gateway_agent_client # raises if PHASEO_API_KEY is missing
)

puts result.output
puts "#{result.run.status} #{result.usage[:total_tokens]}"
```

```java Java theme={null}
import app.phaseo.agent.AgentSdk;
import java.time.Duration;
import java.util.List;
import java.util.Map;

var lookup = AgentSdk.defineTool(new AgentSdk.Tool(
    "lookup_docs",
    (input, context) -> Map.of("topic", ((Map<?, ?>) input).get("topic"), "found", true),
    "Look up a Phaseo documentation topic",
    Map.of(
        "type", "object",
        "properties", Map.of("topic", Map.of("type", "string")),
        "required", List.of("topic")),
    Duration.ofSeconds(10)
));

var agent = AgentSdk.createAgent(new AgentSdk.AgentDefinition(
    "docs-agent",                       // id
    "openai/gpt-6-astra",               // model
    null,                               // preset
    "Use tools when helpful and finish with a concise answer.", // instructions
    List.of(lookup),                    // tools
    6,                                  // maxSteps
    null, null, null, null              // parseOutput, humanReview, modelRetry, toolExecution
));

var result = agent.run(new AgentSdk.RunOptions(
    "Explain when to use routing presets.",  // input
    AgentSdk.createGatewayAgentClient(),     // throws if PHASEO_API_KEY is missing
    null, null, null, null, null, null, null, null
));

System.out.println(result.output());
System.out.println(result.run().status() + " " + result.usage().totalTokens());
```

```rust Rust theme={null}
use phaseo_agent::{
    create_agent, create_gateway_agent_client, define_tool, AgentDefinition,
    RunOptions, Tool,
};
use serde_json::json;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let lookup = define_tool(Tool::new(
        "lookup_docs",
        "Look up a Phaseo documentation topic",
        json!({
            "type": "object",
            "properties": {
                "topic": { "type": "string" }
            },
            "required": ["topic"]
        }),
        |input, context| {
            Ok(json!({
                "topic": input["topic"],
                "run_id": context.run_id,
                "found": true
            }))
        },
    ));

    let agent = create_agent(
        AgentDefinition::new("docs-agent", "openai/gpt-6-astra")
            .instructions("Use lookup_docs when helpful. Answer concisely.")
            .max_steps(6)
            .tool(lookup),
    );

    let mut client = create_gateway_agent_client("openai/gpt-6-astra")?;
    let result = agent.run(
        &mut client,
        RunOptions::new("Explain when to use routing presets."),
    )?;

    println!("{}", result.output);
    println!("steps: {}", result.run.step_count);
    println!("tokens: {}", result.usage.total_tokens);
    Ok(())
}
```

معرّف الأداة هو اسم الدالة الذي يراه النموذج، ومعاملاتها هي JSON Schema الذي يملؤه النموذج. تصل الوسائط إلى شيفرتك بالشكل الأصلي لكل لغة:

| اللغة | ما تستقبله الأداة | ملاحظات |
| - | - | - |
| TypeScript | كائن محدد النوع | `execute(input, context)` |
| Python | `dict` | `execute(tool_input, runtime)` |
| Go | `any` (JSON مفكوك، عادةً `map[string]any`) | `Execute(input, runtime) (any, error)` |
| C# | `JsonElement` | `Execute(input, runtime)`، مع انتظاره (await) |
| PHP | مصفوفة ترابطية | `execute(array $input, $runtime)` |
| Ruby | Hash بمفاتيح نصية | ابنِ الأدوات باستخدام `PhaseoAgentSdk::Tool.new`؛ تعيد `define_tool` ما تمرّره إليها كما هو، لذا لن يعمل Hash عادي |
| Java | `Map` | السجلات موضعية؛ مرّر `null` لأي شيء لا تضبطه |
| Rust | `serde_json::Value` | يعمل الإغلاق (closure) محليًا؛ ويحتوي `RuntimeContext` على معرّف التشغيل ومعرّف الوكيل وفهرس الخطوة وسياق التطبيق واستدعاء الأداة |

إذا لم يحدد الوكيل ولا التشغيل ولا العميل نموذجًا أو إعدادًا مسبقًا، يرسل عميل Gateway القيمة `phaseo/free`. أما `create_gateway_agent_client` في Rust فتأخذ النموذج وسيطًا.

## كيف يعمل التشغيل

```mermaid theme={null}
flowchart TD
  start([تشغيل]) --> turn[إرسال الرسائل إلى النموذج]
  turn --> exec[تنفيذ استدعاءات الأدوات التي لا تحتاج إدخالًا، وإلحاق نتائجها]
  exec --> gate{{"هل ينتظر استدعاءٌ موافقةً أو شخصًا أو مخرجات يدوية؟"}}
  gate -- نعم --> paused([إعادة التشغيل: waiting_for_human])
  gate -- لا --> stopcheck{{"تحقق شرط الإيقاف؟"}}
  stopcheck -- نعم --> stopped([إعادة التشغيل: stopped])
  stopcheck -- لا --> more{{"هل استدعى النموذج أدوات؟"}}
  more -- لا --> done([إعادة التشغيل: completed])
  more -- نعم --> limit{{"هل استُنفد حد الخطوات؟"}}
  limit -- نعم --> failed([فشل: Max steps exceeded])
  limit -- لا --> turn
  paused -. متابعة .-> turn
```

تُحفظ كل خطوة كنقطة حفظ في نتيجة التشغيل المعادة. للاستئناف عبر الطلبات أو بعد إعادة التشغيل، احفظ تلك النتيجة في مخزنك الخاص ومرّرها إلى دالة المتابعة، أو امنح الوكيل أداة وصول إلى الحالة؛ راجع [الحالة والموافقة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/state-and-approval.md). يختلف حد الخطوات وما يحدث عند استنفاده حسب اللغة:

> [tab] TypeScript
>
> يأخذ كل استدعاء لـ `run()` أو `continueRun()` ما يصل إلى 12 خطوة ما لم تضبط `maxSteps`؛ وبعد ذلك يرمي `Max steps exceeded`. استخدم [شروط الإيقاف](https://phaseo.app/docs/ar/v1/sdk-reference/agent/stop-conditions.md) لإنهاء التشغيل بشكل نظيف.

> [tab] Python
>
> يأخذ التشغيل ما يصل إلى 12 خطوة ما لم تضبط `max_steps`؛ وبعد ذلك يرفع `RuntimeError`. لا تُفحص شروط الإيقاف إلا في خطوة لا يستدعي فيها النموذج أي أداة، لذا يختلف الترتيب عن المخطط: تستمر حلقة الأدوات حتى تتوقف مؤقتًا، أو تجيب، أو تستنفد `max_steps`.

> [tab] Go
>
> يفشل التشغيل الذي يحتاج إلى أكثر من `MaxSteps` من أدوار النموذج (الافتراضي 8) بالخطأ `Max steps exceeded (N)`.

> [tab] C#
>
> يرمي التشغيل الذي يحتاج إلى أكثر من `MaxSteps` من أدوار النموذج (الافتراضي 12) الاستثناء `InvalidOperationException("Max steps exceeded (N)")`.

> [tab] PHP
>
> يرمي التشغيل الذي يحتاج إلى أكثر من `maxSteps` من أدوار النموذج (الافتراضي 12) الاستثناء `Max steps exceeded (N)`.

> [tab] Ruby
>
> يرفع التشغيل الذي يحتاج إلى أكثر من `max_steps` من أدوار النموذج (الافتراضي 12) الاستثناء `Max steps exceeded (N)`.

> [tab] Java
>
> يرمي التشغيل الذي يحتاج إلى أكثر من `maxSteps` من أدوار النموذج (الافتراضي 12) الاستثناء `Max steps exceeded (N)`.

> [tab] Rust
>
> يأخذ التشغيل ما يصل إلى 8 أدوار للنموذج ما لم تستدعِ `.max_steps(n)` أو تضبط `RunOptions.max_steps`. بلوغ الحد لا يسبب فشلًا: يعود التشغيل بقيمة `run.status` تساوي `stopped` وقيمة `run.stop_reason` تساوي `max_steps:<limit>`. عمليات التشغيل متزامنة وتُنفَّذ الأدوات المحلية واحدة تلو الأخرى، لذا استخدم خيطًا عاملًا أو حدًّا لمهمة عندما لا ينبغي أن يحجب التشغيل معالج الطلبات.

## اقرأ نتيجة التشغيل

يعيد كل تشغيل الأجزاء نفسها. تتبع أسماء الحقول نمط الكتابة في كل لغة (`output`، `Output`، `output()`):

| الجزء | المحتوى |
| - | - |
| `run` | الحالة والمعرّفات والنموذج الفعلي وحد الخطوات والسياق وحالة التوقف المؤقت وسبب الإيقاف |
| `steps` | سجل واحد لكل دور للنموذج: معرّف الطلب والمزوّد والنموذج وسبب الانتهاء والتحذيرات واستدعاءات الأدوات والاستخدام |
| `messages` | المحادثة كاملة، بما فيها نتائج الأدوات |
| `output` | المخرجات النهائية |
| `usage` | رموز الإدخال والإخراج والمخزّنة مؤقتًا والإجمالية، والتكلفة |

تأتي `usage.cost` في Rust فقط من قيمة رقمية `meta.cost` أو `cost` في الاستجابة؛ ولا تحوّل `cost_nanos` أو `cost_cents`. استخدم استجابة Gateway أو سجل التوليد لتقارير الإنفاق في Rust.

## اعثر على الميزة المناسبة

| لكي… | الصفحة |
| - | - |
| تمنح النموذج أدوات محلية أو يدوية أو تبلّغ عن التقدم | [الأدوات](https://phaseo.app/docs/ar/v1/sdk-reference/agent/tools.md) |
| تتوقف مؤقتًا للموافقة أو لشخص، ثم تستأنف | [الحالة والموافقة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/state-and-approval.md) |
| تعرض النص ونشاط الأدوات لحظة حدوثه | [البث](https://phaseo.app/docs/ar/v1/sdk-reference/agent/streaming.md) |
| تعرض خطًا زمنيًا للرسائل والاستدلال واستدعاءات الأدوات | [العناصر](https://phaseo.app/docs/ar/v1/sdk-reference/agent/items.md) |
| تحدّ الخطوات أو الرموز أو التكلفة أو الوقت | [شروط الإيقاف](https://phaseo.app/docs/ar/v1/sdk-reference/agent/stop-conditions.md) |
| تغيّر النموذج أو الأدوات بين الأدوار | [الأدوار الديناميكية](https://phaseo.app/docs/ar/v1/sdk-reference/agent/dynamic-turns.md) |
| تحصل على مخرجات محددة النوع، أو تعيد محاولة استدعاءات النموذج، أو تستخدم إعدادًا مسبقًا | [المخرجات وإعادة المحاولة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/run-controls.md) |
| تسجّل كل خطوة أو تدققها | [خطافات دورة الحياة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/lifecycle-hooks.md) |
| تسجّل الاستخدام والتكلفة ومعرّفات الطلبات لتشغيل ما | [المراقبة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/observability.md) |
| تعالج أخطاء Gateway والمخطط وحد الخطوات | [الأحداث والأخطاء](https://phaseo.app/docs/ar/v1/sdk-reference/agent/events-and-errors.md) |
| تفحص عمليات التشغيل محليًا | [DevTools](https://phaseo.app/docs/ar/v1/sdk-reference/agent/devtools.md) |

كل تصدير مدرج في [مرجع API](https://phaseo.app/docs/ar/v1/sdk-reference/agent/api-reference.md)، والوكلاء الكاملون موجودون في [الأمثلة](https://phaseo.app/docs/ar/v1/sdk-reference/agent/examples.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.