diff --git a/include/libssh2.h b/include/libssh2.h
index 5a22be2..b50a001 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -638,6 +638,8 @@ LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
  libssh2_channel_setenv_ex((channel), (varname), strlen(varname), (value), \
                            strlen(value))
 
+LIBSSH2_API int libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel);
+
 LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel,
                                                const char *term,
                                                unsigned int term_len,
diff --git a/src/channel.c b/src/channel.c
index 9e29492..54910ef 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -973,6 +973,158 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel,
                           "Unable to complete request for channel request-pty");
 }
 
+/**
+ * channel_request_auth_agent
+ * The actual re-entrant method which requests an auth agent.
+ * */
+static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel,
+                                      const char *request_str,
+                                      int request_str_len)
+{
+    LIBSSH2_SESSION *session = channel->session;
+    unsigned char *s;
+    static const unsigned char reply_codes[3] =
+        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
+    int rc;
+
+    if (channel->req_auth_agent_state == libssh2_NB_state_idle) {
+        /* Only valid options are "auth-agent-req" and
+         * "auth-agent-req@openssh.com" so we make sure it is not
+         * actually longer than the longest possible. */
+        if(request_str_len > 26) {
+            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
+                                  "request_str length too large");
+        }
+
+        /*
+         *  Length: 24 or 36 = packet_type(1) + channel(4) + req_len(4) +
+         *    request_str (variable) + want_reply (1) */
+        channel->req_auth_agent_packet_len = 10 + request_str_len;
+
+        /* Zero out the requireev state to reset */
+        memset(&channel->req_auth_agent_requirev_state, 0,
+               sizeof(channel->req_auth_agent_requirev_state));
+
+        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+                       "Requesting auth agent on channel %lu/%lu",
+                       channel->local.id, channel->remote.id);
+
+        /*
+         *  byte      SSH_MSG_CHANNEL_REQUEST
+         *  uint32    recipient channel
+         *  string    "auth-agent-req"
+         *  boolean   want reply
+         * */
+        s = channel->req_auth_agent_packet;
+        *(s++) = SSH_MSG_CHANNEL_REQUEST;
+        _libssh2_store_u32(&s, channel->remote.id);
+        _libssh2_store_str(&s, (char *)request_str, request_str_len);
+        *(s++) = 0x01;
+
+        channel->req_auth_agent_state = libssh2_NB_state_created;
+    }
+
+    if (channel->req_auth_agent_state == libssh2_NB_state_created) {
+        /* Send the packet, we can use sizeof() on the packet because it
+         * is always completely filled; there are no variable length fields. */
+        rc = _libssh2_transport_send(session, channel->req_auth_agent_packet,
+                                     channel->req_auth_agent_packet_len,
+                                     NULL, 0);
+
+        if (rc == LIBSSH2_ERROR_EAGAIN) {
+            _libssh2_error(session, rc,
+                           "Would block sending auth-agent request");
+        } else if (rc) {
+            channel->req_auth_agent_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, rc,
+                                  "Unable to send auth-agent request");
+        }
+
+        _libssh2_htonu32(channel->req_auth_agent_local_channel,
+                         channel->local.id);
+
+        channel->req_auth_agent_state = libssh2_NB_state_sent;
+    }
+
+    if (channel->req_auth_agent_state == libssh2_NB_state_sent) {
+        unsigned char *data;
+        size_t data_len;
+        unsigned char code;
+
+        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
+                                      1, channel->req_auth_agent_local_channel,
+                                      4, &channel->req_auth_agent_requirev_state);
+
+        if (rc == LIBSSH2_ERROR_EAGAIN) {
+            return rc;
+        } else if (rc) {
+            channel->req_auth_agent_state = libssh2_NB_state_idle;
+            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
+                                  "Failed to request auth-agent");
+        }
+
+        code = data[0];
+
+        LIBSSH2_FREE(session, data);
+        channel->req_auth_agent_state = libssh2_NB_state_idle;
+
+        if (code == SSH_MSG_CHANNEL_SUCCESS)
+            return 0;
+    }
+
+    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
+                          "Unable to complete request for auth-agent");
+}
+
+/*
+ * libssh2_channel_request_auth_agent
+ * Requests that agent forwarding be enabled for the session. The
+ * request must be sent over a specific channel, which starts the agent
+ * listener on the remote side. Once the channel is closed, the agent
+ * listener continues to exist.
+ * */
+LIBSSH2_API int
+libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
+{
+    int rc;
+
+    if (!channel)
+        return LIBSSH2_ERROR_BAD_USE;
+
+    /* The current RFC draft for agent forwarding says you're supposed to
+     * send "auth-agent-req," but most SSH servers out there right now
+     * actually expect "auth-agent-req@openssh.com," so we try that
+     * first. */
+    if (channel->req_auth_agent_try_state == libssh2_NB_state_idle) {
+        BLOCK_ADJUST(rc, channel->session,
+                     channel_request_auth_agent(channel,
+                                                "auth-agent-req@openssh.com",
+                                                26));
+
+        /* If we failed (but not with EAGAIN), then we move onto
+         * the next step to try another request type. */
+        if (rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
+            channel->req_auth_agent_try_state = libssh2_NB_state_sent;
+    }
+
+    if (channel->req_auth_agent_try_state == libssh2_NB_state_sent) {
+        BLOCK_ADJUST(rc, channel->session,
+                     channel_request_auth_agent(channel,
+                                                "auth-agent-req", 14));
+
+        /* If we failed without an EAGAIN, then move on with this
+         * state machine. */
+        if (rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
+            channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
+    }
+
+    /* If things are good, reset the try state. */
+    if (rc == 0)
+        channel->req_auth_agent_try_state = libssh2_NB_state_idle;
+
+    return rc;
+}
+
 /*
  * libssh2_channel_request_pty_ex
  * Duh... Request a PTY
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
index c670a16..1f4da40 100644
--- a/src/libssh2_priv.h
+++ b/src/libssh2_priv.h
@@ -428,6 +428,13 @@ struct _LIBSSH2_CHANNEL
     /* State variables used in libssh2_channel_handle_extended_data2() */
     libssh2_nonblocking_states extData2_state;
 
+    /* State variables used in libssh2_channel_request_auth_agent() */
+    libssh2_nonblocking_states req_auth_agent_try_state;
+    libssh2_nonblocking_states req_auth_agent_state;
+    unsigned char req_auth_agent_packet[36];
+    size_t req_auth_agent_packet_len;
+    unsigned char req_auth_agent_local_channel[4];
+    packet_requirev_state_t req_auth_agent_requirev_state;
 };
 
 struct _LIBSSH2_LISTENER
