{"meta":{"title":"Créez votre première application avec Copilot","intro":"Dans ce tutoriel, vous allez utiliser le kit de développement logiciel (SDK) Copilot pour créer un assistant de ligne de commande. Vous commencerez par les principes de base, ajouterez des réponses en continu, puis des outils personnalisés, ce qui permettra à Copilot d’appeler votre code.","product":"GitHub Copilot","breadcrumbs":[{"href":"/fr/copilot","title":"GitHub Copilot"},{"href":"/fr/copilot/how-tos","title":"Procédures"},{"href":"/fr/copilot/how-tos/copilot-sdk","title":"Kit de développement logiciel (SDK) Copilot"},{"href":"/fr/copilot/how-tos/copilot-sdk/getting-started","title":"Getting Started"}],"documentType":"article"},"body":"# Créez votre première application avec Copilot\n\nDans ce tutoriel, vous allez utiliser le kit de développement logiciel (SDK) Copilot pour créer un assistant de ligne de commande. Vous commencerez par les principes de base, ajouterez des réponses en continu, puis des outils personnalisés, ce qui permettra à Copilot d’appeler votre code.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n**Ce que vous allez construire :**\n\n```text\nYou: What's the weather like in Seattle?\nCopilot: Let me check the weather for Seattle...\n         Currently 62°F and cloudy with a chance of rain.\n         Typical Seattle weather!\n\nYou: How about Tokyo?\nCopilot: In Tokyo it's 75°F and sunny. Great day to be outside!\n```\n\n## Prerequisites\n\nAvant de commencer, assurez-vous d’avoir :\n\n* **GitHub Copilot CLI** installée et authentifiée (le Node.js, le Python et les kits SDK .NET fournissent automatiquement l’interface CLI, voir [Configuration par défaut (interface CLI groupée)](/fr/copilot/how-tos/copilot-sdk/setup/bundled-cli). Obligatoire pour Go, Java et Rust, sauf si vous utilisez leurs fonctionnalités de regroupement CLI au niveau de l’application.)\n* Votre runtime de langage préféré :\n  * **Node.js** 20+ ou **Python** 3.11+ ou **Go** 1.24+ ou **Rust** 1.94+ ou **Java** 17+ ou **.NET** 8.0+\n\nVérifiez que l’interface CLI fonctionne :\n\n```bash\ncopilot --version\n```\n\n## Étape 1 : installer le Kit de développement logiciel (SDK)\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\nTout d’abord, créez un répertoire et initialisez votre projet :\n\n```bash\nmkdir copilot-demo && cd copilot-demo\nnpm init -y --init-type module\n```\n\nInstallez ensuite le Kit de développement logiciel (SDK) et l’exécuteur TypeScript :\n\n```bash\nnpm install @github/copilot-sdk tsx\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n```bash\npip install github-copilot-sdk\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\nTout d’abord, créez un répertoire et initialisez votre module :\n\n```bash\nmkdir copilot-demo && cd copilot-demo\ngo mod init copilot-demo\n```\n\nInstallez ensuite le Kit de développement logiciel (SDK) :\n\n```bash\ngo get github.com/github/copilot-sdk/go\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\nCommencez par créer une crate binaire :\n\n```bash\ncargo new copilot-demo && cd copilot-demo\n```\n\nInstallez ensuite le Kit de développement logiciel (SDK) et les dépendances directes utilisées par les exemples :\n\n```bash\ncargo add github-copilot-sdk --features derive\n# Used by #[tokio::main] and tokio::spawn\ncargo add tokio --features rt-multi-thread,macros\n# Used by custom-tool parameter derives later in this guide\ncargo add serde --features derive\ncargo add schemars\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\nTout d’abord, créez un projet de console :\n\n```bash\ndotnet new console -n CopilotDemo && cd CopilotDemo\n```\n\nAjoutez ensuite le Kit de développement logiciel (SDK) :\n\n```bash\ndotnet add package GitHub.Copilot.SDK\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\nTout d’abord, créez un répertoire et initialisez votre projet.\n\n**Maven** : ajouter à votre `pom.xml`:\n\n```xml\n<dependency>\n    <groupId>com.github</groupId>\n    <artifactId>copilot-sdk-java</artifactId>\n    <version>${copilot.sdk.version}</version>\n</dependency>\n```\n\n**Gradle** : ajouter à votre `build.gradle`:\n\n```groovy\nimplementation 'com.github:copilot-sdk-java:${copilotSdkVersion}'\n```\n\n</div>\n\n</div>\n\n## Étape 2 : envoyer votre premier message\n\nCréez un fichier et ajoutez le code suivant. Il s’agit du moyen le plus simple d’utiliser le Kit de développement logiciel (SDK) : environ 5 lignes de code.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\nCréez `index.ts` :\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\nconst session = await client.createSession({ model: \"auto\" });\n\nconst response = await session.sendAndWait({ prompt: \"What is 2 + 2?\" });\nconsole.log(response?.data.content);\n\nawait client.stop();\nprocess.exit(0);\n```\n\nExécutez-le :\n\n```bash\nnpx tsx index.ts\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\nCréez `main.py` :\n\n```python\nimport asyncio\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n\n    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"auto\")\n    response = await session.send_and_wait(\"What is 2 + 2?\")\n    print(response.data.content)\n\n    await client.stop()\n\nasyncio.run(main())\n```\n\nExécutez-le :\n\n```bash\npython main.py\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\nCréez `main.go` :\n\n```golang\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"os\"\n\n    copilot \"github.com/github/copilot-sdk/go\"\n)\n\nfunc main() {\n    ctx := context.Background()\n    client := copilot.NewClient(nil)\n    if err := client.Start(ctx); err != nil {\n        log.Fatal(err)\n    }\n    defer client.Stop()\n\n    session, err := client.CreateSession(ctx, &copilot.SessionConfig{Model: \"auto\"})\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    response, err := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"What is 2 + 2?\"})\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    if d, ok := response.Data.(*copilot.AssistantMessageData); ok {\n        fmt.Println(d.Content)\n    }\n    os.Exit(0)\n}\n```\n\nExécutez-le :\n\n```bash\ngo run main.go\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\nCréez `src/main.rs` :\n\n```rust\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse github_copilot_sdk::handler::ApproveAllHandler;\nuse github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = Client::start(ClientOptions::default()).await?;\n    let session = client\n        .create_session(SessionConfig::default().with_permission_handler(Arc::new(ApproveAllHandler)))\n        .await?;\n\n    let response = session\n        .send_and_wait(\n            MessageOptions::new(\"What is 2 + 2?\").with_wait_timeout(Duration::from_secs(120)),\n        )\n        .await?;\n\n    if let Some(event) = response {\n        if let Some(content) = event.data.get(\"content\").and_then(|value| value.as_str()) {\n            println!(\"{content}\");\n        }\n    }\n\n    session.disconnect().await?;\n    client.stop().await?;\n    Ok(())\n}\n```\n\nExécutez-le :\n\n```bash\ncargo run\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\nCréez un projet de console et ajoutez-le à `Program.cs`:\n\n```csharp\nusing GitHub.Copilot;\n\nawait using var client = new CopilotClient();\nawait using var session = await client.CreateSessionAsync(new SessionConfig\n{\n    Model = \"auto\",\n    OnPermissionRequest = PermissionHandler.ApproveAll\n});\n\nvar response = await session.SendAndWaitAsync(new MessageOptions { Prompt = \"What is 2 + 2?\" });\nConsole.WriteLine(response?.Data.Content);\n```\n\nExécutez-le :\n\n```bash\ndotnet run\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\nCréez `HelloCopilot.java` :\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\npublic class HelloCopilot {\n    public static void main(String[] args) throws Exception {\n        try (var client = new CopilotClient()) {\n            client.start().get();\n\n            var session = client.createSession(\n                new SessionConfig()\n                    .setModel(\"auto\")\n                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n            ).get();\n\n            var response = session.sendAndWait(\n                new MessageOptions().setPrompt(\"What is 2 + 2?\")\n            ).get();\n\n            System.out.println(response.getData().content());\n\n            client.stop().get();\n        }\n    }\n}\n```\n\nExécutez-le :\n\n```bash\njavac -cp copilot-sdk.jar HelloCopilot.java && java -cp .:copilot-sdk.jar HelloCopilot\n```\n\n</div>\n\n</div>\n\n**Vous devez voir :**\n\n```text\n4\n```\n\nFélicitations! Vous venez de créer votre première application optimisée par Copilot.\n\n## Étape 3 : ajouter des réponses en streaming\n\nÀ l’heure actuelle, vous attendez la réponse complète avant de voir quoi que ce soit. Rendons cela interactif en diffusant la réponse au fil de sa génération.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\nMettez à jour `index.ts` :\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient();\nconst session = await client.createSession({\n    model: \"auto\",\n    streaming: true,\n});\n\n// Listen for response chunks\nsession.on(\"assistant.message_delta\", (event) => {\n    process.stdout.write(event.data.deltaContent);\n});\nsession.on(\"session.idle\", () => {\n    console.log(); // New line when done\n});\n\nawait session.sendAndWait({ prompt: \"Tell me a short joke\" });\n\nawait client.stop();\nprocess.exit(0);\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\nMettez à jour `main.py` :\n\n```python\nimport asyncio\nimport sys\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\nfrom copilot.session_events import SessionEventType\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n\n    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"auto\", streaming=True)\n\n    # Listen for response chunks\n    def handle_event(event):\n        if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:\n            sys.stdout.write(event.data.delta_content)\n            sys.stdout.flush()\n        if event.type == SessionEventType.SESSION_IDLE:\n            print()  # New line when done\n\n    session.on(handle_event)\n\n    await session.send_and_wait(\"Tell me a short joke\")\n\n    await client.stop()\n\nasyncio.run(main())\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\nMettez à jour `main.go` :\n\n```golang\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"os\"\n\n    copilot \"github.com/github/copilot-sdk/go\"\n)\n\nfunc main() {\n    ctx := context.Background()\n    client := copilot.NewClient(nil)\n    if err := client.Start(ctx); err != nil {\n        log.Fatal(err)\n    }\n    defer client.Stop()\n\n    session, err := client.CreateSession(ctx, &copilot.SessionConfig{\n        Model:     \"auto\",\n        Streaming: copilot.Bool(true),\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Listen for response chunks\n    session.On(func(event copilot.SessionEvent) {\n        switch d := event.Data.(type) {\n        case *copilot.AssistantMessageDeltaData:\n            fmt.Print(d.DeltaContent)\n        case *copilot.SessionIdleData:\n            _ = d\n            fmt.Println()\n        }\n    })\n\n    _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"Tell me a short joke\"})\n    if err != nil {\n        log.Fatal(err)\n    }\n    os.Exit(0)\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\nMettez à jour `src/main.rs` :\n\n```rust\nuse std::io::{self, Write};\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse github_copilot_sdk::handler::ApproveAllHandler;\nuse github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = Client::start(ClientOptions::default()).await?;\n\n    let mut config = SessionConfig::default();\n    config.streaming = Some(true);\n    let session = client\n        .create_session(config.with_permission_handler(Arc::new(ApproveAllHandler)))\n        .await?;\n\n    // Listen for response chunks\n    let mut events = session.subscribe();\n    tokio::spawn(async move {\n        while let Ok(event) = events.recv().await {\n            match event.event_type.as_str() {\n                \"assistant.message_delta\" => {\n                    if let Some(text) =\n                        event.data.get(\"deltaContent\").and_then(|value| value.as_str())\n                    {\n                        print!(\"{text}\");\n                        io::stdout().flush().ok();\n                    }\n                }\n                \"assistant.message\" => println!(),\n                _ => {}\n            }\n        }\n    });\n\n    session\n        .send_and_wait(\n            MessageOptions::new(\"Tell me a short joke\")\n                .with_wait_timeout(Duration::from_secs(120)),\n        )\n        .await?;\n\n    session.disconnect().await?;\n    client.stop().await?;\n    Ok(())\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\nMettez à jour `Program.cs` :\n\n```csharp\nusing GitHub.Copilot;\n\nawait using var client = new CopilotClient();\nawait using var session = await client.CreateSessionAsync(new SessionConfig\n{\n    Model = \"auto\",\n    OnPermissionRequest = PermissionHandler.ApproveAll,\n    Streaming = true,\n});\n\n// Listen for response chunks\nsession.On<SessionEvent>(ev =>\n{\n    if (ev is AssistantMessageDeltaEvent deltaEvent)\n    {\n        Console.Write(deltaEvent.Data.DeltaContent);\n    }\n    if (ev is SessionIdleEvent)\n    {\n        Console.WriteLine();\n    }\n});\n\nawait session.SendAndWaitAsync(new MessageOptions { Prompt = \"Tell me a short joke\" });\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\nMettez à jour `HelloCopilot.java` :\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\npublic class HelloCopilot {\n    public static void main(String[] args) throws Exception {\n        try (var client = new CopilotClient()) {\n            client.start().get();\n\n            var session = client.createSession(\n                new SessionConfig()\n                    .setModel(\"auto\")\n                    .setStreaming(true)\n                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n            ).get();\n\n            // Listen for response chunks\n            session.on(AssistantMessageDeltaEvent.class, delta -> {\n                System.out.print(delta.getData().deltaContent());\n            });\n            session.on(SessionIdleEvent.class, idle -> {\n                System.out.println(); // New line when done\n            });\n\n            session.sendAndWait(\n                new MessageOptions().setPrompt(\"Tell me a short joke\")\n            ).get();\n\n            client.stop().get();\n        }\n    }\n}\n```\n\n</div>\n\n</div>\n\nRéexécutez le code. Vous verrez la réponse s’afficher mot par mot.\n\n### Méthodes d’abonnement aux événements\n\nLe Kit de développement logiciel (SDK) fournit des méthodes d’abonnement aux événements de session :\n\n| Méthode                  | Description                                                                                                       |\n| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| `on(handler)`            | S’abonner à tous les événements ; renvoie la fonction de désabonnement                                            |\n| `on(eventType, handler)` | S’abonner à un type d’événement spécifique (Node.js/TypeScript uniquement) ; renvoie la fonction de désabonnement |\n| `subscribe()`            | S’abonner à tous les événements (Rust) ; filtrer par `event_type`                                                 |\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\n// Subscribe to all events\nconst unsubscribeAll = session.on((event) => {\n    console.log(\"Event:\", event.type);\n});\n\n// Subscribe to specific event type\nconst unsubscribeIdle = session.on(\"session.idle\", (event) => {\n    console.log(\"Session is idle\");\n});\n\n// Later, to unsubscribe:\nunsubscribeAll();\nunsubscribeIdle();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n```python\n# Subscribe to all events\nunsubscribe = session.on(lambda event: print(f\"Event: {event.type}\"))\n\n# Filter by event type in your handler\ndef handle_event(event):\n    if event.type == SessionEventType.SESSION_IDLE:\n        print(\"Session is idle\")\n    elif event.type == SessionEventType.ASSISTANT_MESSAGE:\n        print(f\"Message: {event.data.content}\")\n\nunsubscribe = session.on(handle_event)\n\n# Later, to unsubscribe:\nunsubscribe()\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n```golang\n// Subscribe to all events\nunsubscribe := session.On(func(event copilot.SessionEvent) {\n    fmt.Println(\"Event:\", event.Type)\n})\n\n// Filter by event type in your handler\nsession.On(func(event copilot.SessionEvent) {\n    switch d := event.Data.(type) {\n    case *copilot.SessionIdleData:\n        _ = d\n        fmt.Println(\"Session is idle\")\n    case *copilot.AssistantMessageData:\n        fmt.Println(\"Message:\", d.Content)\n    }\n})\n\n// Later, to unsubscribe:\nunsubscribe()\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n```rust\nlet mut events = session.subscribe();\n\ntokio::spawn(async move {\n    while let Ok(event) = events.recv().await {\n        println!(\"Event: {}\", event.event_type);\n\n        match event.event_type.as_str() {\n            \"session.idle\" => println!(\"Session is idle\"),\n            \"assistant.message\" => {\n                if let Some(content) = event.data.get(\"content\").and_then(|value| value.as_str()) {\n                    println!(\"Message: {content}\");\n                }\n            }\n            _ => {}\n        }\n    }\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n```csharp\n// Subscribe to all events\nvar unsubscribe = session.On<SessionEvent>(ev => Console.WriteLine($\"Event: {ev.Type}\"));\n\n// Filter by event type using pattern matching\nsession.On<SessionEvent>(ev =>\n{\n    switch (ev)\n    {\n        case SessionIdleEvent:\n            Console.WriteLine(\"Session is idle\");\n            break;\n        case AssistantMessageEvent msg:\n            Console.WriteLine($\"Message: {msg.Data.Content}\");\n            break;\n    }\n});\n\n// Later, to unsubscribe:\nunsubscribe.Dispose();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n<!-- docs-validate: skip -->\n\n```java\n// Subscribe to all events\nvar unsubscribe = session.on(event -> {\n    System.out.println(\"Event: \" + event.getType());\n});\n\n// Subscribe to a specific event type\nsession.on(AssistantMessageEvent.class, msg -> {\n    System.out.println(\"Message: \" + msg.getData().content());\n});\n\nsession.on(SessionIdleEvent.class, idle -> {\n    System.out.println(\"Session is idle\");\n});\n\n// Later, to unsubscribe:\nunsubscribe.close();\n```\n\n</div>\n\n</div>\n\n## Étape 4 : ajouter un outil personnalisé\n\nPassons maintenant à la partie la plus puissante. Donnez à Copilot la possibilité d’appeler votre code en définissant un outil personnalisé. Nous allons créer un outil de recherche météo simple.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\nMettez à jour `index.ts` :\n\n```typescript\nimport { CopilotClient, defineTool } from \"@github/copilot-sdk\";\n\n// Define a tool that Copilot can call\nconst getWeather = defineTool(\"get_weather\", {\n    description: \"Get the current weather for a city\",\n    parameters: {\n        type: \"object\",\n        properties: {\n            city: { type: \"string\", description: \"The city name\" },\n        },\n        required: [\"city\"],\n    },\n    handler: async (args: { city: string }) => {\n        const { city } = args;\n        // In a real app, you'd call a weather API here\n        const conditions = [\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"];\n        const temp = Math.floor(Math.random() * 30) + 50;\n        const condition = conditions[Math.floor(Math.random() * conditions.length)];\n        return { city, temperature: `${temp}°F`, condition };\n    },\n});\n\nconst client = new CopilotClient();\nconst session = await client.createSession({\n    model: \"auto\",\n    streaming: true,\n    tools: [getWeather],\n});\n\nsession.on(\"assistant.message_delta\", (event) => {\n    process.stdout.write(event.data.deltaContent);\n});\n\nsession.on(\"session.idle\", () => {\n    console.log(); // New line when done\n});\n\nawait session.sendAndWait({\n    prompt: \"What's the weather like in Seattle and Tokyo?\",\n});\n\nawait client.stop();\nprocess.exit(0);\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\nMettez à jour `main.py` :\n\n```python\nimport asyncio\nimport random\nimport sys\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\nfrom copilot.tools import define_tool\nfrom copilot.session_events import SessionEventType\nfrom pydantic import BaseModel, Field\n\n# Define the parameters for the tool using Pydantic\nclass GetWeatherParams(BaseModel):\n    city: str = Field(description=\"The name of the city to get weather for\")\n\n# Define a tool that Copilot can call\n@define_tool(description=\"Get the current weather for a city\")\nasync def get_weather(params: GetWeatherParams) -> dict:\n    city = params.city\n    # In a real app, you'd call a weather API here\n    conditions = [\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"]\n    temp = random.randint(50, 80)\n    condition = random.choice(conditions)\n    return {\"city\": city, \"temperature\": f\"{temp}°F\", \"condition\": condition}\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n\n    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"auto\", streaming=True, tools=[get_weather])\n\n    def handle_event(event):\n        if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:\n            sys.stdout.write(event.data.delta_content)\n            sys.stdout.flush()\n        if event.type == SessionEventType.SESSION_IDLE:\n            print()\n\n    session.on(handle_event)\n\n    await session.send_and_wait(\"What's the weather like in Seattle and Tokyo?\")\n\n    await client.stop()\n\nasyncio.run(main())\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\nMettez à jour `main.go` :\n\n```golang\npackage main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"math/rand\"\n    \"os\"\n\n    copilot \"github.com/github/copilot-sdk/go\"\n)\n\n// Define the parameter type\ntype WeatherParams struct {\n    City string `json:\"city\" jsonschema:\"The city name\"`\n}\n\n// Define the return type\ntype WeatherResult struct {\n    City        string `json:\"city\"`\n    Temperature string `json:\"temperature\"`\n    Condition   string `json:\"condition\"`\n}\n\nfunc main() {\n    ctx := context.Background()\n\n    // Define a tool that Copilot can call\n    getWeather := copilot.DefineTool(\n        \"get_weather\",\n        \"Get the current weather for a city\",\n        func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {\n            // In a real app, you'd call a weather API here\n            conditions := []string{\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"}\n            temp := rand.Intn(30) + 50\n            condition := conditions[rand.Intn(len(conditions))]\n            return WeatherResult{\n                City:        params.City,\n                Temperature: fmt.Sprintf(\"%d°F\", temp),\n                Condition:   condition,\n            }, nil\n        },\n    )\n\n    client := copilot.NewClient(nil)\n    if err := client.Start(ctx); err != nil {\n        log.Fatal(err)\n    }\n    defer client.Stop()\n\n    session, err := client.CreateSession(ctx, &copilot.SessionConfig{\n        Model:     \"auto\",\n        Streaming: copilot.Bool(true),\n        Tools:     []copilot.Tool{getWeather},\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    session.On(func(event copilot.SessionEvent) {\n        switch d := event.Data.(type) {\n        case *copilot.AssistantMessageDeltaData:\n            fmt.Print(d.DeltaContent)\n        case *copilot.SessionIdleData:\n            _ = d\n            fmt.Println()\n        }\n    })\n\n    _, err = session.SendAndWait(ctx, copilot.MessageOptions{\n        Prompt: \"What's the weather like in Seattle and Tokyo?\",\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n    os.Exit(0)\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\nMettez à jour `src/main.rs` :\n\n```rust\nuse std::io::{self, Write};\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse github_copilot_sdk::handler::ApproveAllHandler;\nuse github_copilot_sdk::tool::{define_tool, JsonSchema};\nuse github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig, ToolResult};\nuse serde::Deserialize;\n\n#[derive(Deserialize, JsonSchema)]\nstruct GetWeatherParams {\n    city: String,\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    // Define a tool that Copilot can call\n    let tools = vec![define_tool(\n        \"get_weather\",\n        \"Get the current weather for a city\",\n        |_inv, params: GetWeatherParams| async move {\n            Ok(ToolResult::Text(format!(\n                \"{}: 62°F and sunny\",\n                params.city\n            )))\n        },\n    )];\n\n    let client = Client::start(ClientOptions::default()).await?;\n\n    let mut config = SessionConfig::default();\n    config.streaming = Some(true);\n    let session = client\n        .create_session(\n            config\n                .with_tools(tools)\n                .with_permission_handler(Arc::new(ApproveAllHandler)),\n        )\n        .await?;\n\n    let mut events = session.subscribe();\n    tokio::spawn(async move {\n        while let Ok(event) = events.recv().await {\n            match event.event_type.as_str() {\n                \"assistant.message_delta\" => {\n                    if let Some(text) =\n                        event.data.get(\"deltaContent\").and_then(|value| value.as_str())\n                    {\n                        print!(\"{text}\");\n                        io::stdout().flush().ok();\n                    }\n                }\n                \"assistant.message\" => println!(),\n                _ => {}\n            }\n        }\n    });\n\n    session\n        .send_and_wait(\n            MessageOptions::new(\"What's the weather like in Seattle and Tokyo?\")\n                .with_wait_timeout(Duration::from_secs(120)),\n        )\n        .await?;\n\n    session.disconnect().await?;\n    client.stop().await?;\n    Ok(())\n}\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\nMettez à jour `Program.cs` :\n\n```csharp\nusing GitHub.Copilot;\nusing Microsoft.Extensions.AI;\nusing System.ComponentModel;\n\nawait using var client = new CopilotClient();\n\n// Define a tool that Copilot can call\nvar getWeather = CopilotTool.DefineTool(\n    ([Description(\"The city name\")] string city) =>\n    {\n        // In a real app, you'd call a weather API here\n        var conditions = new[] { \"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\" };\n        var temp = Random.Shared.Next(50, 80);\n        var condition = conditions[Random.Shared.Next(conditions.Length)];\n        return new { city, temperature = $\"{temp}°F\", condition };\n    },\n    factoryOptions: new AIFunctionFactoryOptions\n    {\n        Name = \"get_weather\",\n        Description = \"Get the current weather for a city\",\n    }\n);\n\nawait using var session = await client.CreateSessionAsync(new SessionConfig\n{\n    Model = \"auto\",\n    OnPermissionRequest = PermissionHandler.ApproveAll,\n    Streaming = true,\n    Tools = [getWeather],\n});\n\nsession.On<SessionEvent>(ev =>\n{\n    if (ev is AssistantMessageDeltaEvent deltaEvent)\n    {\n        Console.Write(deltaEvent.Data.DeltaContent);\n    }\n    if (ev is SessionIdleEvent)\n    {\n        Console.WriteLine();\n    }\n});\n\nawait session.SendAndWaitAsync(new MessageOptions\n{\n    Prompt = \"What's the weather like in Seattle and Tokyo?\",\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\nMettez à jour `HelloCopilot.java` :\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.concurrent.CompletableFuture;\n\npublic class HelloCopilot {\n    public static void main(String[] args) throws Exception {\n        var random = new Random();\n        var conditions = List.of(\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\");\n\n        // Define a tool that Copilot can call\n        var getWeather = ToolDefinition.create(\n            \"get_weather\",\n            \"Get the current weather for a city\",\n            Map.of(\n                \"type\", \"object\",\n                \"properties\", Map.of(\n                    \"city\", Map.of(\"type\", \"string\", \"description\", \"The city name\")\n                ),\n                \"required\", List.of(\"city\")\n            ),\n            invocation -> {\n                var city = (String) invocation.getArguments().get(\"city\");\n                var temp = random.nextInt(30) + 50;\n                var condition = conditions.get(random.nextInt(conditions.size()));\n                return CompletableFuture.completedFuture(Map.of(\n                    \"city\", city,\n                    \"temperature\", temp + \"°F\",\n                    \"condition\", condition\n                ));\n            }\n        );\n\n        try (var client = new CopilotClient()) {\n            client.start().get();\n\n            var session = client.createSession(\n                new SessionConfig()\n                    .setModel(\"auto\")\n                    .setStreaming(true)\n                    .setTools(List.of(getWeather))\n                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n            ).get();\n\n            session.on(AssistantMessageDeltaEvent.class, delta -> {\n                System.out.print(delta.getData().deltaContent());\n            });\n            session.on(SessionIdleEvent.class, idle -> {\n                System.out.println();\n            });\n\n            session.sendAndWait(\n                new MessageOptions().setPrompt(\"What's the weather like in Seattle and Tokyo?\")\n            ).get();\n\n            client.stop().get();\n        }\n    }\n}\n```\n\n</div>\n\n</div>\n\nExécutez-la et vous verrez Copilot appeler votre outil pour obtenir des données météorologiques, puis répondre avec les résultats !\n\n## Étape 5 : créer un assistant interactif\n\nMettons-le ensemble dans un assistant interactif utile :\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\nimport { CopilotClient, defineTool } from \"@github/copilot-sdk\";\nimport * as readline from \"readline\";\n\nconst getWeather = defineTool(\"get_weather\", {\n    description: \"Get the current weather for a city\",\n    parameters: {\n        type: \"object\",\n        properties: {\n            city: { type: \"string\", description: \"The city name\" },\n        },\n        required: [\"city\"],\n    },\n    handler: async ({ city }) => {\n        const conditions = [\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"];\n        const temp = Math.floor(Math.random() * 30) + 50;\n        const condition = conditions[Math.floor(Math.random() * conditions.length)];\n        return { city, temperature: `${temp}°F`, condition };\n    },\n});\n\nconst client = new CopilotClient();\nconst session = await client.createSession({\n    model: \"auto\",\n    streaming: true,\n    tools: [getWeather],\n});\n\nsession.on(\"assistant.message_delta\", (event) => {\n    process.stdout.write(event.data.deltaContent);\n});\n\nconst rl = readline.createInterface({\n    input: process.stdin,\n    output: process.stdout,\n});\n\nconsole.log(\"🌤️  Weather Assistant (type 'exit' to quit)\");\nconsole.log(\"   Try: 'What's the weather in Paris?'\\n\");\n\nconst prompt = () => {\n    rl.question(\"You: \", async (input) => {\n        if (input.toLowerCase() === \"exit\") {\n            await client.stop();\n            rl.close();\n            return;\n        }\n\n        process.stdout.write(\"Assistant: \");\n        await session.sendAndWait({ prompt: input });\n        console.log(\"\\n\");\n        prompt();\n    });\n};\n\nprompt();\n```\n\nExécutez avec :\n\n```bash\nnpx tsx weather-assistant.ts\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\nCréez `weather_assistant.py` :\n\n```python\nimport asyncio\nimport random\nimport sys\nfrom copilot import CopilotClient\nfrom copilot.session import PermissionHandler\nfrom copilot.tools import define_tool\nfrom copilot.session_events import SessionEventType\nfrom pydantic import BaseModel, Field\n\nclass GetWeatherParams(BaseModel):\n    city: str = Field(description=\"The name of the city to get weather for\")\n\n@define_tool(description=\"Get the current weather for a city\")\nasync def get_weather(params: GetWeatherParams) -> dict:\n    city = params.city\n    conditions = [\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"]\n    temp = random.randint(50, 80)\n    condition = random.choice(conditions)\n    return {\"city\": city, \"temperature\": f\"{temp}°F\", \"condition\": condition}\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n\n    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"auto\", streaming=True, tools=[get_weather])\n\n    def handle_event(event):\n        if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:\n            sys.stdout.write(event.data.delta_content)\n            sys.stdout.flush()\n\n    session.on(handle_event)\n\n    print(\"🌤️  Weather Assistant (type 'exit' to quit)\")\n    print(\"   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\\n\")\n\n    while True:\n        try:\n            user_input = input(\"You: \")\n        except EOFError:\n            break\n\n        if user_input.lower() == \"exit\":\n            break\n\n        sys.stdout.write(\"Assistant: \")\n        await session.send_and_wait(user_input)\n        print(\"\\n\")\n\n    await client.stop()\n\nasyncio.run(main())\n```\n\nExécutez avec :\n\n```bash\npython weather_assistant.py\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\nCréez `weather-assistant.go` :\n\n```golang\npackage main\n\nimport (\n    \"bufio\"\n    \"context\"\n    \"fmt\"\n    \"log\"\n    \"math/rand\"\n    \"os\"\n    \"strings\"\n\n    copilot \"github.com/github/copilot-sdk/go\"\n)\n\ntype WeatherParams struct {\n    City string `json:\"city\" jsonschema:\"The city name\"`\n}\n\ntype WeatherResult struct {\n    City        string `json:\"city\"`\n    Temperature string `json:\"temperature\"`\n    Condition   string `json:\"condition\"`\n}\n\nfunc main() {\n    ctx := context.Background()\n\n    getWeather := copilot.DefineTool(\n        \"get_weather\",\n        \"Get the current weather for a city\",\n        func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {\n            conditions := []string{\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\"}\n            temp := rand.Intn(30) + 50\n            condition := conditions[rand.Intn(len(conditions))]\n            return WeatherResult{\n                City:        params.City,\n                Temperature: fmt.Sprintf(\"%d°F\", temp),\n                Condition:   condition,\n            }, nil\n        },\n    )\n\n    client := copilot.NewClient(nil)\n    if err := client.Start(ctx); err != nil {\n        log.Fatal(err)\n    }\n    defer client.Stop()\n\n    session, err := client.CreateSession(ctx, &copilot.SessionConfig{\n        Model:     \"auto\",\n        Streaming: copilot.Bool(true),\n        Tools:     []copilot.Tool{getWeather},\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    session.On(func(event copilot.SessionEvent) {\n        switch d := event.Data.(type) {\n        case *copilot.AssistantMessageDeltaData:\n            fmt.Print(d.DeltaContent)\n        case *copilot.SessionIdleData:\n            _ = d\n            fmt.Println()\n        }\n    })\n\n    fmt.Println(\"🌤️  Weather Assistant (type 'exit' to quit)\")\n    fmt.Println(\"   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\\n\")\n\n    scanner := bufio.NewScanner(os.Stdin)\n    for {\n        fmt.Print(\"You: \")\n        if !scanner.Scan() {\n            break\n        }\n        input := scanner.Text()\n        if strings.ToLower(input) == \"exit\" {\n            break\n        }\n\n        fmt.Print(\"Assistant: \")\n        _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: input})\n        if err != nil {\n            fmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\n            break\n        }\n        fmt.Println()\n    }\n    if err := scanner.Err(); err != nil {\n        fmt.Fprintf(os.Stderr, \"Input error: %v\\n\", err)\n    }\n}\n```\n\nExécutez avec :\n\n```bash\ngo run weather-assistant.go\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\nCréez `src/main.rs` :\n\n```rust\nuse std::io::{self, BufRead, Write};\nuse std::sync::Arc;\nuse std::time::Duration;\n\nuse github_copilot_sdk::handler::ApproveAllHandler;\nuse github_copilot_sdk::tool::{define_tool, JsonSchema};\nuse github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig, ToolResult};\nuse serde::Deserialize;\n\n#[derive(Deserialize, JsonSchema)]\nstruct GetWeatherParams {\n    city: String,\n}\n\nfn read_line() -> Option<String> {\n    let stdin = io::stdin();\n    let mut line = String::new();\n    stdin.lock().read_line(&mut line).ok()?;\n    if line.is_empty() {\n        return None;\n    }\n    Some(line.trim_end_matches(&['\\n', '\\r'][..]).to_string())\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let tools = vec![define_tool(\n        \"get_weather\",\n        \"Get the current weather for a city\",\n        |_inv, params: GetWeatherParams| async move {\n            Ok(ToolResult::Text(format!(\n                \"{}: 62°F and sunny\",\n                params.city\n            )))\n        },\n    )];\n\n    let client = Client::start(ClientOptions::default()).await?;\n\n    let mut config = SessionConfig::default();\n    config.streaming = Some(true);\n    let session = client\n        .create_session(\n            config\n                .with_tools(tools)\n                .with_permission_handler(Arc::new(ApproveAllHandler)),\n        )\n        .await?;\n\n    let mut events = session.subscribe();\n    tokio::spawn(async move {\n        while let Ok(event) = events.recv().await {\n            match event.event_type.as_str() {\n                \"assistant.message_delta\" => {\n                    if let Some(text) =\n                        event.data.get(\"deltaContent\").and_then(|value| value.as_str())\n                    {\n                        print!(\"{text}\");\n                        io::stdout().flush().ok();\n                    }\n                }\n                \"assistant.message\" => println!(),\n                _ => {}\n            }\n        }\n    });\n\n    println!(\"Weather Assistant (type 'exit' to quit)\");\n    println!(\"Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\\n\");\n\n    loop {\n        print!(\"You: \");\n        io::stdout().flush().ok();\n\n        let Some(input) = read_line() else { break };\n        if input.eq_ignore_ascii_case(\"exit\") {\n            break;\n        }\n\n        print!(\"Assistant: \");\n        io::stdout().flush().ok();\n        session\n            .send_and_wait(MessageOptions::new(input).with_wait_timeout(Duration::from_secs(120)))\n            .await?;\n        println!();\n    }\n\n    session.disconnect().await?;\n    client.stop().await?;\n    Ok(())\n}\n```\n\nExécutez avec :\n\n```bash\ncargo run\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\nCréez un projet de console et mettez à jour `Program.cs`:\n\n```csharp\nusing GitHub.Copilot;\nusing Microsoft.Extensions.AI;\nusing System.ComponentModel;\n\n// Define the weather tool\nvar getWeather = CopilotTool.DefineTool(\n    ([Description(\"The city name\")] string city) =>\n    {\n        var conditions = new[] { \"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\" };\n        var temp = Random.Shared.Next(50, 80);\n        var condition = conditions[Random.Shared.Next(conditions.Length)];\n        return new { city, temperature = $\"{temp}°F\", condition };\n    },\n    factoryOptions: new AIFunctionFactoryOptions\n    {\n        Name = \"get_weather\",\n        Description = \"Get the current weather for a city\",\n    });\n\nawait using var client = new CopilotClient();\nawait using var session = await client.CreateSessionAsync(new SessionConfig\n{\n    Model = \"auto\",\n    OnPermissionRequest = PermissionHandler.ApproveAll,\n    Streaming = true,\n    Tools = [getWeather]\n});\n\n// Listen for response chunks\nsession.On<SessionEvent>(ev =>\n{\n    if (ev is AssistantMessageDeltaEvent deltaEvent)\n    {\n        Console.Write(deltaEvent.Data.DeltaContent);\n    }\n    if (ev is SessionIdleEvent)\n    {\n        Console.WriteLine();\n    }\n});\n\nConsole.WriteLine(\"🌤️  Weather Assistant (type 'exit' to quit)\");\nConsole.WriteLine(\"   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\\n\");\n\nwhile (true)\n{\n    Console.Write(\"You: \");\n    var input = Console.ReadLine();\n\n    if (string.IsNullOrEmpty(input) || input.Equals(\"exit\", StringComparison.OrdinalIgnoreCase))\n    {\n        break;\n    }\n\n    Console.Write(\"Assistant: \");\n    await session.SendAndWaitAsync(new MessageOptions { Prompt = input });\n    Console.WriteLine(\"\\n\");\n}\n```\n\nExécutez avec :\n\n```bash\ndotnet run\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\nCréez `WeatherAssistant.java` :\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.Scanner;\nimport java.util.concurrent.CompletableFuture;\n\npublic class WeatherAssistant {\n    public static void main(String[] args) throws Exception {\n        var random = new Random();\n        var conditions = List.of(\"sunny\", \"cloudy\", \"rainy\", \"partly cloudy\");\n\n        var getWeather = ToolDefinition.create(\n            \"get_weather\",\n            \"Get the current weather for a city\",\n            Map.of(\n                \"type\", \"object\",\n                \"properties\", Map.of(\n                    \"city\", Map.of(\"type\", \"string\", \"description\", \"The city name\")\n                ),\n                \"required\", List.of(\"city\")\n            ),\n            invocation -> {\n                var city = (String) invocation.getArguments().get(\"city\");\n                var temp = random.nextInt(30) + 50;\n                var condition = conditions.get(random.nextInt(conditions.size()));\n                return CompletableFuture.completedFuture(Map.of(\n                    \"city\", city,\n                    \"temperature\", temp + \"°F\",\n                    \"condition\", condition\n                ));\n            }\n        );\n\n        try (var client = new CopilotClient()) {\n            client.start().get();\n\n            var session = client.createSession(\n                new SessionConfig()\n                    .setModel(\"auto\")\n                    .setStreaming(true)\n                    .setOnPermissionRequest(request ->\n                        CompletableFuture.completedFuture(PermissionDecision.allow())\n                    )\n                    .setTools(List.of(getWeather))\n            ).get();\n\n            session.on(AssistantMessageDeltaEvent.class, delta -> {\n                System.out.print(delta.getData().deltaContent());\n            });\n            session.on(SessionIdleEvent.class, idle -> {\n                System.out.println();\n            });\n\n            System.out.println(\"🌤️  Weather Assistant (type 'exit' to quit)\");\n            System.out.println(\"   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\\n\");\n\n            var scanner = new Scanner(System.in);\n            while (true) {\n                System.out.print(\"You: \");\n                if (!scanner.hasNextLine()) break;\n                var input = scanner.nextLine();\n                if (input.equalsIgnoreCase(\"exit\")) break;\n\n                System.out.print(\"Assistant: \");\n                session.sendAndWait(\n                    new MessageOptions().setPrompt(input)\n                ).get();\n                System.out.println(\"\\n\");\n            }\n\n            client.stop().get();\n        }\n    }\n}\n```\n\nExécutez avec :\n\n```bash\njavac -cp copilot-sdk.jar WeatherAssistant.java && java -cp .:copilot-sdk.jar WeatherAssistant\n```\n\n</div>\n\n</div>\n\n**Exemple de session :**\n\n```text\n🌤️  Weather Assistant (type 'exit' to quit)\n   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\n\nYou: What's the weather in Seattle?\nAssistant: Let me check the weather for Seattle...\nIt's currently 62°F and cloudy in Seattle.\n\nYou: How about Tokyo and London?\nAssistant: I'll check both cities for you:\n- Tokyo: 75°F and sunny\n- London: 58°F and rainy\n\nYou: exit\n```\n\nVous avez créé un assistant avec un outil personnalisé que Copilot peut appeler !\n\n## Fonctionnement des outils\n\nLorsque vous définissez un outil, vous indiquez Copilot :\n\n1. **Rôle de l’outil** (description)\n2. **Paramètres dont il a besoin** (schéma)\n3. **Code à exécuter** (gestionnaire)\n\nCopilot décide quand appeler votre outil en fonction de la question de l'utilisateur. Quand cela se produit :\n\n1. Copilot envoie une demande d’appel d’outil avec les paramètres\n2. Le Kit de développement logiciel (SDK) exécute votre fonction de gestionnaire\n3. Le résultat est renvoyé à Copilot\n4. Copilot incorpore le résultat dans sa réponse\n\n## Quelle est l’étape suivante ?\n\nMaintenant que vous avez les bases, voici des fonctionnalités plus puissantes à explorer :\n\n### Se connecter aux serveurs MCP\n\nLes serveurs MCP (Model Context Protocol) fournissent des outils prédéfini. Connectez-vous au serveur MCP de GitHub pour permettre à Copilot d’accéder aux dépôts, aux tickets et aux pull requests :\n\n```typescript\nconst session = await client.createSession({\n    mcpServers: {\n        github: {\n            type: \"http\",\n            url: \"https://api.githubcopilot.com/mcp/\",\n        },\n    },\n});\n```\n\n📖\n\\*\\*\n[Utilisation de serveurs MCP avec le SDK GitHub Copilot](/fr/copilot/how-tos/copilot-sdk/features/mcp)\\*\\* - Découvrez les serveurs locaux et distants, toutes les options de configuration et la résolution des problèmes.\n\n### Créer des agents personnalisés\n\nDéfinissez des personnages d’IA spécialisés pour des tâches spécifiques :\n\n```typescript\nconst session = await client.createSession({\n    customAgents: [{\n        name: \"pr-reviewer\",\n        displayName: \"PR Reviewer\",\n        description: \"Reviews pull requests for best practices\",\n        prompt: \"You are an expert code reviewer. Focus on security, performance, and maintainability.\",\n    }],\n});\n```\n\n> \\[!TIP]\n> Vous pouvez également définir `agent: \"pr-reviewer\"` dans la configuration de session pour pré-sélectionner cet agent à partir du démarrage. Pour plus d’informations, consultez [autoTITLE](/fr/copilot/how-tos/copilot-sdk/features/custom-agents#selecting-an-agent-at-session-creation) .\n\n### Personnaliser le message système\n\nContrôlez le comportement et la personnalité de l’IA en ajoutant des instructions :\n\n```typescript\nconst session = await client.createSession({\n    systemMessage: {\n        content: \"You are a helpful assistant for our engineering team. Always be concise.\",\n    },\n});\n```\n\nPour un contrôle plus précis, utilisez `mode: \"customize\"` pour remplacer des sections individuelles de l’invite système tout en préservant le reste :\n\n```typescript\nconst session = await client.createSession({\n    systemMessage: {\n        mode: \"customize\",\n        sections: {\n            tone: { action: \"replace\", content: \"Respond in a warm, professional tone. Be thorough in explanations.\" },\n            code_change_rules: { action: \"remove\" },\n            guidelines: { action: \"append\", content: \"\\n* Always cite data sources\" },\n        },\n        content: \"Focus on financial analysis and reporting.\",\n    },\n});\n```\n\nID de section disponible : `preamble`, , `identity``tone`, . `runtime_instructions``last_instructions``tool_efficiency``environment_context``code_change_rules``guidelines``safety``tool_instructions``custom_instructions`\n\n`identity` et `tool_instructions` sont *des groupes* de sections : ils ciblent une collection de sous-sections connexes sous forme d’unité. Utilisez `preamble` pour cibler uniquement le préambule d’identité sans affecter ses sous-sections homologues.\n\nChaque remplacement prend en charge cinq actions : `replace`, `remove`, `append`, `prepend` et `preserve`. L’action `preserve` est une no-op qui choisit une section adressable individuellement hors d’un niveau `remove` de groupe (par exemple, conserver `tone` lors de la suppression du `identity` groupe). Les ID de section inconnus sont gérés correctement : le contenu issu des remplacements `replace`/`append`/`prepend` est ajouté aux instructions supplémentaires, et les remplacements `remove` sont ignorés sans avertissement.\n\nConsultez les fichiers README des SDK spécifiques à chaque langage pour voir des exemples en [TypeScript](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md), [Python](https://github.com/github/copilot-sdk/tree/main/python/README.md), [Go](https://github.com/github/copilot-sdk/tree/main/go/README.md), [Rust](https://github.com/github/copilot-sdk/tree/main/rust/README.md), [Java](https://github.com/github/copilot-sdk/tree/main/java/README.md) et [C#](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md).\n\n## Connexion à un serveur CLI externe\n\nPar défaut, le Kit de développement logiciel (SDK) gère automatiquement le cycle de vie du processus cli Copilot, en démarrant et en arrêtant l’interface CLI si nécessaire. Toutefois, vous pouvez également exécuter l’interface CLI en mode serveur séparément et connecter le Kit de développement logiciel (SDK). Cela peut être utile pour :\n\n* **Débogage** : laissez l’outil en ligne de commande en cours d’exécution entre les redémarrages du SDK afin de consulter les journaux\n* **Partage de ressources** : plusieurs clients du Kit de développement logiciel (SDK) peuvent se connecter au même serveur CLI\n* **Développement** : Exécuter l’interface CLI avec des paramètres personnalisés ou dans un autre environnement\n\n### Exécution de l’interface CLI en mode serveur\n\nDémarrez l’interface CLI en mode serveur à l’aide de l’indicateur `--headless` et spécifiez éventuellement un port :\n\n```bash\ncopilot --headless --port 4321\n```\n\nSi vous ne spécifiez pas de port, l’interface CLI choisit un port disponible aléatoire.\n\nPar défaut, le serveur headless accepte uniquement les connexions loopback (`127.0.0.1`), donc le SDK doit s’exécuter sur la même machine. Pour accepter les connexions à partir d’autres hôtes (par exemple, lors de l’exécution de l’interface CLI dans un conteneur ou sur un serveur distinct), liez-vous à une adresse sans bouclage avec `--host`:\n\n```bash\n# Listen on all interfaces\ncopilot --headless --host 0.0.0.0 --port 4321\n```\n\n> \\[!WARNING]\n> L’exposition du serveur sans interface utilisateur sur une adresse autre qu’une adresse de bouclage le rend accessible à toute personne pouvant acheminer du trafic vers cette adresse. Associez-le à des contrôles réseau (pare-feu, réseau privé, proxy inverse) et l’authentification appropriée pour votre environnement.\n\n### Connexion du Kit de développement logiciel (SDK) au serveur externe\n\nUne fois que l’interface CLI s’exécute en mode serveur, configurez votre client SDK pour qu’il se connecte à celui-ci à l’aide de l’option « URL cli » :\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n```typescript\nimport { CopilotClient, approveAll } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient({\n    cliUrl: \"localhost:4321\"\n});\n\n// Use the client normally\nconst session = await client.createSession({ onPermissionRequest: approveAll });\n// ...\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n```python\nfrom copilot import CopilotClient, RuntimeConnection\nfrom copilot.session import PermissionHandler\n\nclient = CopilotClient(connection=RuntimeConnection.for_uri(\"localhost:4321\"))\nawait client.start()\n\n# Use the client normally\nsession = await client.create_session(on_permission_request=PermissionHandler.approve_all)\n# ...\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n```golang\nimport copilot \"github.com/github/copilot-sdk/go\"\n\nclient := copilot.NewClient(&copilot.ClientOptions{\n    Connection: copilot.URIConnection{URL: \"localhost:4321\"},\n})\n\nif err := client.Start(ctx); err != nil {\n    log.Fatal(err)\n}\ndefer client.Stop()\n\n// Use the client normally\nsession, err := client.CreateSession(ctx, &copilot.SessionConfig{\n    OnPermissionRequest: copilot.PermissionHandler.ApproveAll,\n})\n// ...\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n```rust\nuse std::sync::Arc;\n\nuse github_copilot_sdk::handler::ApproveAllHandler;\nuse github_copilot_sdk::{Client, ClientOptions, SessionConfig, Transport};\n\nlet mut options = ClientOptions::default();\noptions.transport = Transport::External {\n    host: \"localhost\".to_string(),\n    port: 4321,\n    connection_token: None,\n};\nlet client = Client::start(options).await?;\n\n// Use the client normally\nlet session = client\n    .create_session(SessionConfig::default().with_permission_handler(Arc::new(ApproveAllHandler)))\n    .await?;\n// ...\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n```csharp\nusing GitHub.Copilot;\n\nusing var client = new CopilotClient(new CopilotClientOptions\n{\n    Connection = RuntimeConnection.ForUri(\"localhost:4321\"),\n});\n\n// Use the client normally\nawait using var session = await client.CreateSessionAsync(new()\n{\n    OnPermissionRequest = PermissionHandler.ApproveAll\n});\n// ...\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\nvar client = new CopilotClient(\n    new CopilotClientOptions().setCliUrl(\"localhost:4321\")\n);\nclient.start().get();\n\n// Use the client normally\nvar session = client.createSession(\n    new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n).get();\n// ...\n```\n\n</div>\n\n</div>\n\n**Remarque :** Lorsque `cli_url` / `cliUrl` / le `URIConnection` de Go est fourni, ou que Rust utilise `Transport::External`, le SDK ne lancera ni ne gérera de processus CLI - il se contentera de se connecter au serveur existant à l’URL spécifiée.\n\n## Télémétrie et observabilité\n\nLe SDK Copilot prend en charge [OpenTelemetry](https://opentelemetry.io/) pour le suivi distribué. Fournissez une `telemetry` configuration au client pour permettre l’exportation de trace à partir du processus CLI et de la propagation automatique du contexte de trace [W3C](https://www.w3.org/TR/trace-context/) entre le Kit de développement logiciel (SDK) et l’interface CLI.\n\n### Activation de la télémétrie\n\nTransmettez une `telemetry` configuration (ou `Telemetry`) lors de la création du client. Il s’agit de l’option d’adhésion : aucun indicateur « activé » distinct n’est nécessaire.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n<!-- docs-validate: skip -->\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\n\nconst client = new CopilotClient({\n  telemetry: {\n    otlpEndpoint: \"http://localhost:4318\",\n  },\n});\n```\n\nDépendance de pair facultative : `@opentelemetry/api`\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n<!-- docs-validate: skip -->\n\n```python\nfrom copilot import CopilotClient, CopilotClientOptions\n\nclient = CopilotClient(CopilotClientOptions(\n    telemetry={\n        \"otlp_endpoint\": \"http://localhost:4318\",\n    },\n))\n```\n\nInstaller avec les options de télémétrie : `pip install copilot-sdk[telemetry]` (fournit `opentelemetry-api`)\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n<!-- docs-validate: skip -->\n\n```golang\nclient := copilot.NewClient(&copilot.ClientOptions{\n    Telemetry: &copilot.TelemetryConfig{\n        OTLPEndpoint: \"http://localhost:4318\",\n    },\n})\n```\n\nDépendance: `go.opentelemetry.io/otel`\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n<!-- docs-validate: skip -->\n\n```rust\nuse github_copilot_sdk::{Client, ClientOptions, OtelExporterType, TelemetryConfig};\n\nlet mut options = ClientOptions::default();\noptions.telemetry = Some(\n    TelemetryConfig::new()\n        .with_exporter_type(OtelExporterType::OtlpHttp)\n        .with_otlp_endpoint(\"http://localhost:4318\"),\n);\nlet client = Client::start(options).await?;\n```\n\nAucune dépendance supplémentaire : le SDK injecte des variables d’environnement de télémétrie pour le processus CLI généré.\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n<!-- docs-validate: skip -->\n\n```csharp\nvar client = new CopilotClient(new CopilotClientOptions\n{\n    Telemetry = new TelemetryConfig\n    {\n        OtlpEndpoint = \"http://localhost:4318\",\n    },\n});\n```\n\nAucune dépendance supplémentaire : utilise le prédéfini `System.Diagnostics.Activity`.\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n<!-- docs-validate: skip -->\n\n```java\nimport com.github.copilot.CopilotClient;\nimport com.github.copilot.rpc.*;\n\nvar client = new CopilotClient(new CopilotClientOptions()\n    .setTelemetry(new TelemetryConfig()\n        .setOtlpEndpoint(\"http://localhost:4318\")));\n```\n\nDépendance: `io.opentelemetry:opentelemetry-api`\n\n</div>\n\n</div>\n\n### Options de configuration de télémétrie\n\n| Option                     | Node.js          | Python            | Allez            | Rust              | Java             | .NET             | Description                                                                    |\n| -------------------------- | ---------------- | ----------------- | ---------------- | ----------------- | ---------------- | ---------------- | ------------------------------------------------------------------------------ |\n| Point de terminaison OTLP  | `otlpEndpoint`   | `otlp_endpoint`   | `OTLPEndpoint`   | `otlp_endpoint`   | `otlpEndpoint`   | `OtlpEndpoint`   | URL du point de terminaison HTTP OTLP                                          |\n| Protocole OTLP             | `otlpProtocol`   | `otlp_protocol`   | `OTLPProtocol`   | `otlp_protocol`   | `otlpProtocol`   | `OtlpProtocol`   | Protocole HTTP OTLP pour tous les signaux : `\"http/json\"` ou `\"http/protobuf\"` |\n| Chemins d'accès au fichier | `filePath`       | `file_path`       | `FilePath`       | `file_path`       | `filePath`       | `FilePath`       | Chemin du fichier pour la sortie trace au format JSON-lines                    |\n| Type d’exportateur         | `exporterType`   | `exporter_type`   | `ExporterType`   | `exporter_type`   | `exporterType`   | `ExporterType`   |                                                                                |\n| `\"otlp-http\"` ou `\"file\"`  |                  |                   |                  |                   |                  |                  |                                                                                |\n| Nom de la source           | `sourceName`     | `source_name`     | `SourceName`     | `source_name`     | `sourceName`     | `SourceName`     | Nom de la portée d’instrumentation                                             |\n| Capturer du contenu        | `captureContent` | `capture_content` | `CaptureContent` | `capture_content` | `captureContent` | `CaptureContent` | Indique s’il faut capturer le contenu du message                               |\n\nLe champ du protocole OTLP configure l’exportateur de l’interface de ligne de commande (CLI) `\"otlp-http\"` pour tous les signaux. Laissez-le vide pour utiliser la valeur par défaut de la CLI, ou définissez-le sur `\"http/protobuf\"` pour exporter des données protobuf via HTTP.\n\n### Exportation de fichiers\n\nPour écrire des traces dans un fichier local au lieu d’un point de terminaison OTLP :\n\n<!-- docs-validate: skip -->\n\n```typescript\nconst client = new CopilotClient({\n  telemetry: {\n    filePath: \"./traces.jsonl\",\n    exporterType: \"file\",\n  },\n});\n```\n\n### Propagation du contexte de trace\n\nLe contexte de trace est propagé automatiquement : aucune instrumentation manuelle n’est nécessaire :\n\n* **SDK → CLI** : les en-têtes `traceparent` et `tracestate` du span/de l’activité en cours sont inclus dans les appels RPC `session.create`, `session.resume` et `session.send`.\n* **CLI → SDK** : lorsque l’interface CLI appelle des gestionnaires d’outils, le contexte de trace de l’étendue de l’interface CLI est propagé afin que le code de votre outil s’exécute sous l’étendue parente correcte.\n\n📖\n\\*\\*\n[Instrumentation OpenTelemetry pour le Kit de développement logiciel (SDK) Copilot](/fr/copilot/how-tos/copilot-sdk/observability/opentelemetry)\\*\\* : options TelemetryConfig, propagation du contexte de trace et dépendances par langage.\n\n## Learn more\n\n* [Authentification](/fr/copilot/how-tos/copilot-sdk/auth/authenticate) - GitHub OAuth, variables d’environnement et BYOK\n* [BYOK (apportez votre propre clé)](/fr/copilot/how-tos/copilot-sdk/auth/byok) - Utilisez vos propres clés API à partir de Microsoft Foundry, OpenAI, etc.\n* [ Informations de référence surNode.js SDK](https://github.com/github/copilot-sdk/tree/main/nodejs/README.md)\n* informations de référence sur [Python SDK](https://github.com/github/copilot-sdk/tree/main/python/README.md)\n* [Référence du SDK Go](https://github.com/github/copilot-sdk/tree/main/go/README.md)\n* [Référence du SDK Rust](https://github.com/github/copilot-sdk/tree/main/rust/README.md)\n* [Référence du SDK .NET](https://github.com/github/copilot-sdk/tree/main/dotnet/README.md)\n* informations de référence sur [Java SDK](https://github.com/github/copilot-sdk/tree/main/java/README.md)\n* [Utilisation de serveurs MCP avec le SDK GitHub Copilot](/fr/copilot/how-tos/copilot-sdk/features/mcp) - Intégrer des outils externes via le protocole de contexte de modèle\n* documentation du serveur MCP [GitHub](https://github.com/github/github-mcp-server)\n* [Répertoire des serveurs MCP](https://github.com/modelcontextprotocol/servers) - Explorer d’autres serveurs MCP\n* [Instrumentation OpenTelemetry pour le Kit de développement logiciel (SDK) Copilot](/fr/copilot/how-tos/copilot-sdk/observability/opentelemetry) - TelemetryConfig, propagation du contexte de trace et dépendances par langage\n\n**Tu as réussi!** Vous avez appris les concepts fondamentaux du Kit de développement logiciel (SDK) GitHub Copilot :\n\n* ✅ Création d’un client et d’une session\n* ✅ Envoi de messages et réception de réponses\n* ✅ Diffusion en continu pour la sortie en temps réel\n* ✅ Définir des outils personnalisés que Copilot peut appeler\n\nMaintenant, allez construire quelque chose d’incroyable !\n🚀"}